Poj 2976 Dropping tests(二分)

来源:互联网 发布:深圳新菜鸟网络俱乐部 编辑:程序博客网 时间:2024/06/09 20:40
题目地址: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;}



0 0
原创粉丝点击