poj2976:dropping tests(0/1分数规划)

来源:互联网 发布:中考倒计时软件下载 编辑:程序博客网 时间:2024/06/05 00:54

Description

In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be.

Given your test scores and a positive integer k, determine how high you can make your cumulative average if you are allowed to drop any k of your test scores.

Suppose you take 3 tests with scores of 5/5, 0/1, and 2/6. Without dropping any tests, your cumulative average is . However, if you drop the third test, your cumulative average becomes .

题意:

给两个数组a[i],b[i],求r=n1a[i]x[i]n1b[i]x[i] 的最大值,其中x[i]有k个为0,其余为一。

0-1分数规划

一、分数规划

分数规划的一般形式:

minλ=f(x)=a(x)b(x)
s.t. xS,b(x)>0

其中,解向量x在解空间S内,a(x),b(x)都是连续的实值函数。

一般解决分数规划问题的实用方法为参数搜索法,即对答案进行猜测,再验证该猜测值,的最优性,将最优化问题转化为判定性问题或其他更容易求解的最优化问题。由于分数规划 模型的特殊性,使得能够构造另外一个由猜测值 作为自变量的相关问题,且该问题的解满足一定的单调性,或其他的可以减小参数搜索范围的性质,从而逼近答案。

假设λ=f(x)为该规划的最优解,有:

λ=f(x)=a(x)b(x)
λb(x)=a(x)
0=a(x)λb(x)

由上面的形式构造一个新函数g(x):

g(λ)=minxS{a(x)λb(x)}

这个函数是一个非分式的规划。先来看看它本身的性质:

单调性:g(λ)是一个严格递减函数,即对于λ1<λ2 ,一定有g(λ1)>g(λ2)

证明:设解向量x1最小化了g(λ1)。则:

g(λ1)=minxS{(a(x1)λ1b(x1)}
=a(x1)λ1b(x1)
>a(x1)λ2b(x1)
minxS{(a(x)λ2b(x))}=g(λ2)

最后一步说明g(λ1)上最小解代入g(?λ2)后不一定还是最小解,甚至有更小解。

有了单调性,就意味着我们可以采用二分搜索的方法来逼近答案。但我们还不知道我们所求的目标是什么,下面考察构造出的新函数与原目标函数的最优解关系:

Dinkelbach定理:设λ为原规划的最优解,则g(λ)=0当且仅当λ=λ
证明:必要性:λ=λg(λ)=0

对于xS ,都不会比x优:

λ=a(x)b(x)a(x)λxb(x)=0

然而x 可以取到这个下限

λ=a(x)b(x)a(x)λb(x)=0

充分性:g(λ)=0λ=λ

若存在一个解x使得g(λ)=0f(x)为原规划最优解。

反证法。反设存在一个解λ=f(x),它是比λ=f(x)更优的解。那么:

λ=a(x)b(x)<λ
a(xλb(x))<0

这时x应该使得g(λ)<0,这与g(λ)=0矛盾。

由上面的性质及定理容易推得:

g(λ)=0λ=λg(λ)<0λ>λg(λ)>0λ<λ

有了该推论我们就可以对最优解进行二分查找,每次需要计算的是一个新的非分数规 划,这就将原问题简化了,以便我们能设计出其他有效的算法解决这个问题。算法的复杂度 是二分迭代的次数与每次解决g(λ)的复杂度的积。

二、0/1分数规划

分数规划的一个特例是0-1分数规划,就是其解向量满足x{0,1}.形式化的定义:

minλ=f(x)=iaixiibixi(x {0,1})
s.t. bx>0

解决0-1分数规划与普通的分数规划一样,也可以采用二分搜索,构建新的规划函数求 解的算法。

例如:给定1个二元组 (ai,bi),求选出k个二元组,使得剩下的 aibi比率最大,即求:

maxiaixiibixi,xi{0,1}

题解:

二分答案r=aixibixi,则最优解满足aixibixi=0
且任意的aixibiximax{r}0因此我们求解g(r)=aixibixir的最优 (大)值即可判断出答案的范围:g(r)>0 则答案偏小,g(r)<0答案偏大。

回到原问题中,我们将每个二元组的价值设为aibir,之后贪心取最大的k个元素即可求得g(r) 的最优值,进而利用二分确定答案。

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<cmath>using namespace std;const int Maxn=1050;const double eps=1e-7;inline int read(){    char ch=getchar();int i=0,f=1;    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}    return i*f;}int n,k;double a[Maxn],b[Maxn],c[Maxn];inline bool check(double r){    for(int i=1;i<=n;i++)c[i]=a[i]-r*b[i];    sort(c+1,c+n+1);    double sum=0;    for(int i=k+1;i<=n;i++)    {        sum+=c[i];    }    return sum>=0;}int main(){    while(1)    {        n=read(),k=read();        if(!n&&!k)break;        for(int i=1;i<=n;i++)a[i]=read();        for(int i=1;i<=n;i++)b[i]=read();        double l=0,r=1.0;        while(r-l>eps)        {            double mid=(l+r)*1.0/2.0;            if(check(mid))l=mid;            else r=mid;        }        printf("%.0f\n",l*100);    }    return 0;}
阅读全文
0 0