您的位置:首页 > 运维架构

POJ 2976 Dropping tests 01分数规划

2013-07-31 13:31 357 查看


POJ 2976 Dropping tests 01分数规划

分类: Algorithm-动态规划2013-07-23
23:06 32人阅读 评论(0) 收藏 举报

01分数规划

第一次做这类型的题目,纪念一下。

题目链接:http://poj.org/problem?id=2976

这是入门级别的01分数规划问题,使用的是二分搜索,不过感觉效率还是不高,试着用Dinkelbach算法优化下。

[cpp] view
plaincopyprint?

#include <iostream>

#include <algorithm>

#include <cstdio>

#include <ctime>

#include <cstdlib>

using namespace std;

const int maxn=1005;

double a[maxn],b[maxn],d[maxn];

const double eps=1e-6;

int n,k;

bool cal(double mid)

{

for(int i=0;i<n;i++)

d[i]=a[i]-mid*b[i];

sort(d,d+n);

double sum=0;

for(int i=k;i<n;i++)

sum+=d[i];

if(sum>0)return 1;

else return 0;

}

int main()

{

while(scanf("%d%d", &n, &k) != EOF)

{

if(n+k==0)break;

for(int i=0;i<n;i++)

scanf("%lf", &a[i]);

for(int i=0;i<n;i++)

scanf("%lf", &b[i]);

double l=0.0,r=1.0;

//clock_t t1=clock();

while(r-l>=eps)

{

double mid=(l+r)/2;

if(cal(mid))l=mid;

else r=mid;

}

printf("%.0f\n", l * 100);

//clock_t t2=clock();

//cout<<t2-t1<<" ms"<<endl;

}

return 0;

}

题目大意: 给定n个二元组(a,b),扔掉k个二元组,使得剩下的a元素之和与b元素之和的比率最大。

题目求的是 max(∑a[i] * x[i] / (b[i] * x[i])) 其中a,b都是一一对应的。 x[i]取0,1 并且 ∑x[i]
= n - k;

那么可以转化一下。 令r = ∑a[i] * x[i] / (b[i] * x[i]) 则必然∑a[i] * x[i] - ∑b[i] * x[i] * r=
0;(条件1)

并且任意的 ∑a[i] * x[i] - ∑b[i] * x[i] * max(r) <=
0 (条件2,只有当∑a[i] * x[i] / (b[i] * x[i]) = max(r) 条件2中等号才成立)

然后就可以枚举r , 对枚举的r, 求Q(r) = ∑a[i] * x[i] - ∑b[i] * x[i] * r 的最大值, 为什么要求最大值呢? 因为我们之前知道了条件2,所以当我们枚举到r为max(r)的值时,显然对于所有的情况Q(r)都会小于等于0,并且Q(r)的最大值一定是0.而我们求最大值的目的就是寻找Q(r)=0的可能性,这样就满足了条件1,最后就是枚举使得Q(r)恰好等于0时就找到了max(r)。而如果能Q(r)>0
说明该r值是偏小的,并且可能存在Q(r)=0,而Q(r)<0的话,很明显是r值偏大的,因为max(r)都是使Q(r)最大值为0,说明不可能存在Q(r)=0了,需要移动上界。


poj Dropping tests 01分数规划---Dinkelbach算法

分类: Algorithm-动态规划2013-07-23
23:57 168人阅读 评论(0) 收藏 举报

01分数规划Dinkelbach算法

果然比二分要快将近一倍。63MS。二分94MS。

[cpp] view
plaincopyprint?

#include <iostream>

#include <algorithm>

#include <cstdio>

#include <ctime>

#include <cstdlib>

#include <cmath>

using namespace std;

const int maxn=1005;

double a[maxn],b[maxn];

const double eps=1e-6;

int n,k;

struct dnode{

double x;

int index;

}d[maxn];

bool cmp(dnode a,dnode b){

return a.x>b.x;

}

int main()

{

while(scanf("%d%d", &n, &k) != EOF)

{

if(n+k==0)break;

for(int i=0;i<n;i++)

scanf("%lf", &a[i]);

for(int i=0;i<n;i++)

scanf("%lf", &b[i]);

double l=0.5,ans;

do{

ans=l;

for(int i=0;i<n;i++)

{d[i].x=a[i]-ans*b[i];

d[i].index=i;

}

sort(d,d+n,cmp);

double p=0,q=0;

for(int i=0;i<n-k;i++)

{

p+=a[d[i].index];

q+=b[d[i].index];

}

l=p/q;

}while(fabs(ans-l)>=eps);

printf("%.0f\n", l * 100);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: