POJ2976-01分数规划&二分-Dropping tests

来源:互联网 发布:淘宝客贷入口 编辑:程序博客网 时间:2024/05/27 14:12

https://vjudge.net/problem/POJ-2976
给定n个人,有两种分数,a,b
要求你选取一部分,要求 sigma(a)/sigma(b) *100得值最大。
化简式子
这里写图片描述
枚举的mid 不断的逼近最优解。 设定一个精度。

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;/* 01分数规划 可以用二分,或者用一种递推。 思路是 不断的维护一个最优解。 因为暴力计算最优解,是不可行的,因为他要找那么那么多那么多组合  而01分数规划是通过对 式子的转化。  如果 sigma(x1-y1*mid) 大于0,如果当前选择的 分数构成的比例已经大于mid  也就是说,必然存在一个更优的解(因为我们当前计算就已经比他优了)  那为什么不用我们 现在计算的那个点呢,  因为可能有些选择比他更优,  (如果没有比他更优的话,最后不断的二分,mid会不断的回退到这里)*/const int maxn=3000;const double eps=1e-5;double  a[maxn];double  b[maxn];double aa[maxn];bool cmp2(double a,double b){    return a<b;}int main(){   int m,k;    while(~scanf("%d%d",&m,&k)){         if(!m&&!k) break;         for(int i=0;i<m;i++){              scanf("%lf",&a[i]);         }         for(int i=0;i<m;i++){             scanf("%lf",&b[i]);         }         double l=0.0;         double r=1.0;         double ans=0;         double mid;         while(r-l>=eps){               mid=(r+l)/2;               //cout<<mid<<endl;              double sum=0;              for(int i=0;i<m;i++){                 aa[i]=a[i]*1.0-b[i]*mid;              }              sort(aa,aa+m,cmp2);              for(int i=k;i<m;i++){                  sum+=aa[i];              }              if(sum>=0){                 l=mid;                 ans=mid;              }              else                r=mid;         }         printf("%.0f\n",ans*100);    }    return 0;}
原创粉丝点击