题目地址:http://poj.org/problem?id=2976
思路:max{sigma(a[i])/sigma(b[i])}。设r=sigma(a[i]*x[i])/sigma(b[i]*x[i])(x[i]=0,1)。则sigma(a[i]*x[i])-r*sigma(b[i]*x[i])=0,而sigma(a[i]*x[i])-max(r)*(sigma(b[i]*x[i]))<=0,当且仅当max(r)=sigma(a[i]*x[i])/sigma(b[i]*x[i])时取等号。则二分r,求f(r)=sigma(a[i]*x[i])-r*sigma(b[i]*x[i])的最大值,若最大值为0,则当前r即为答案(对于r=max(r)时,所有值均不大于0,最大值为0)。若f(r)>0,则l=mid,此时r偏小;若f(r)<0,则r=mid,此时r偏大。求最大值:设tmp[i]=a[i]-r*b[i],将tmp从小到大排序,第k+1到第n个值的和即为当前r下的最大值。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e3+50;
const double eps=1e-7;
int n,k;
double tmp[maxn];
int a[maxn],b[maxn];
int check(double x)
{
for(int i=1;i<=n;i++)
tmp[i]=a[i]-x*b[i];
sort(tmp+1,tmp+n+1);
double sum=0.0;
for(int i=k+1;i<=n;i++) sum+=tmp[i];
return sum>=0;
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF&&n)
{
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
double l=0.0,r=101.0,mid;
while(r-l>=eps)
{
mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid;
}
printf("%d\n",(int)(l*100+0.5));
}
return 0;
}