『POJ 2976』Dropping tests (01分数规划)
Posted fang-hao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了『POJ 2976』Dropping tests (01分数规划)相关的知识,希望对你有一定的参考价值。
Descrip
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 .
题目描述
现在有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("%.0lf
",l);
}
}
以上是关于『POJ 2976』Dropping tests (01分数规划)的主要内容,如果未能解决你的问题,请参考以下文章
POJ-2976 Dropping tests---二分最大化平均值