您的位置:首页 > 其它

POJ 2976 01分数规划

2013-01-09 21:59 351 查看
题意:

给定n个二元组(a,b),删除k个二元组,使得剩下的a元素之和与b元素之和的比率最大(比率最后乘100输出)

题解:

最裸的01分数规划,以此题为例讲述如何构造。

设:xi∈{0,1},表示第i个二元组是否留下,p为比率,P为p的最大值,即比例的最大值(注意区分大P于小p)

则:p=sigma(ai*xi)/sigma(bi*xi) 其中sigma(xi)=n-k

显然:对于所有可能的取得的 p 的值,p<=P

即:对于所有可能的xi的组合,sigma(ai*xi)/sigma(bi*xi)<=P

即:sigma(ai*xi)/sigma(bi*xi)的最大值等于P

即:sigma(ai*xi)-sigma(P*bi*xi)<=0,也就是sigma(ai*xi)-sigma(P*bi*xi)的最大值等于0

由于:sigma(ai*xi)-sigma(p*bi*xi)等价于sigma((ai-bi*p)*xi),sigma((ai-bi*P)*xi)的最大值就等于0

同理:

设:我们枚举的p的最大值为m(对于虽有的xi的组合,不一定存在m这个取值)

若m>P,sigma((ai-bi*P)*xi)的最大值小于0

若m<P,sigma((ai-bi*P)*xi)的最大值大于0

然后通过二分逼近的方法可以求出m=P~

市面上能够见到的01分数规划大都就是这么做~

View Code

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>

#define N 1100

using namespace std;

struct PX
{
double a,b,c;
}px
;

int n,p;
double l,r,mid;

inline bool cmp(const PX &a,const PX &b)
{
return a.c>b.c;
}

inline void read()
{
for(int i=1;i<=n;i++) scanf("%lf",&px[i].a);
for(int i=1;i<=n;i++) scanf("%lf",&px[i].b);
}

inline bool check()
{
for(int i=1;i<=n;i++)
px[i].c=px[i].a-px[i].b*mid;
sort(px+1,px+1+n,cmp);
double ans=0.0;
for(int i=1;i<=n-p;i++) ans+=px[i].c;
if(ans<0.0) return true;
else return false;
}

inline void go()
{
l=0.0; r=1.0;
while(r-l>1e-8)
{
mid=(l+r)/2.0;
if(check())
r=mid;
else l=mid;
}
printf("%.0lf\n",mid*100);
}

int main()
{
while(scanf("%d%d",&n,&p),n||p) read(),go();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: