题意:给定n和k,a1,a2...an和b1,b2...bn
求扔掉k组数ai,bi 后,下面式子的最大值为多少
分析:01规划的基本应用
假设最大值为x
可得: 100*sigma(a[i])/sigma(b[i])=x
----> 100*sigma(a[i])-x*sigma(b[i])=0
----> sigma(100*a[i]-x*b[i])=0
设 f(x)=sigma(100*a[i]-x*b[i])
为单调函数,可以利用二分查找求解
可以先用100*a[i]-r*b[i]进行排序,然后选前面的n-k个数,
然后再去求和,如果sum>=0则low=mid,反之则high=mid
#include<stdio.h>
#include<algorithm>
#define eps 1e-4
using namespace std;
int n,k;
struct stu{
double a,b,rate;
}data[1010];
double sumA,sumB;
int cmp(stu x,stu y)
{
return x.rate>y.rate;
}
bool judge(double mid)
{
for(int i=1;i<=n;i++)
data[i].rate=100*data[i].a-mid*data[i].b;
sort(data+1,data+1+n,cmp);
double sum=0;
for(int i=1;i<=n-k;i++)
sum+=data[i].rate;
if(sum>=0)
return true;
return false;
}
double bin_search(double low,double high)
{
double mid;
while(high-low>eps){
mid=(low+high)/2;
if(judge(mid))
low=mid;
else
high=mid;
}
return mid;
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF){
if(n==0&&k==0)
break;
sumA=sumB=0;
for(int i=1;i<=n;i++){
scanf("%lf",&data[i].a);
sumA+=data[i].a;
}
for(int i=1;i<=n;i++){
scanf("%lf",&data[i].b);
sumB+=data[i].b;
}
double temp=bin_search(sumA*100/sumB,100);
int ans=(int)((temp*10+5)/10);
printf("%d\n",ans);
}
return 0;
}