『POJ 2976』Dropping tests (01分数规划)
题目链接 DescripIn 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 题目描述现在有n个物品,每个物品都有两个价值,一个价值为(a),一个价值为(b),(保证(a_ileq b_i))现在最多可以有k个物品不选,请问能够使选择的物品的(100*frac{sum a_i}{sum b_i})最大是多少? 解题思路显然是一道01分数规划的题目,因为题目中说明了(a_ileq b_i),那最终的取值就只能是(0)到(100)之间,所以我们把那个100提出来,答案的区间就变成了([0,1]),所以,我们可以二分答案去验证可行性。 数学证明假设(frac{sum a_i}{sum b_i}ge x),那就有(sum a_ige x*sum b_i),即(sum a_i-x*sum b_ige0),我们只要处理出每个物品(i)的另一个价值(a_i-x*b_i),然后从大到小排序,计算前(n-k)个物品的价值的和,是否大于等于0就好了。 一点小细节注意一下eps的设置就好了。 代码#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1050; const double eps=1e-5; int n,k; int a[maxn],b[maxn]; double tmp[maxn]; inline bool cmp(double x,double y){ return x>y; } inline bool check(double x){ for(register int i=1;i<=n;i++){ tmp[i]=(double)a[i]-1.0*b[i]*x; } sort(tmp+1,tmp+1+n,cmp); double ans=0; for(register int i=1;i<=n-k;i++)ans+=tmp[i]; return ans>=0; } int main(){ while(~scanf("%d%d",&n,&k)){ if(n+k==0)return 0; for(register int i=1;i<=n;i++)scanf("%d",&a[i]); for(register int i=1;i<=n;i++)scanf("%d",&b[i]); register double l=0.0,r=1.0; while(r-l>eps){ register double m=(l+r)/2; if(check(m))l=m; else r=m; } l*=100; printf("%.0lfn",l); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |