poj 2976(01规划)
题意:
给定n个二元组(a,b),删除k个二元组,使得剩下的a元素之和与b元素之和的比率最大(比率最后乘100输出)
ai<=bi
设 (a1+a2+...an)/(b1+b2+..bn)=m;
则有∑(ai-m*bi)=0
显然m是在0,1之间的。(ai<=bi)
故可二分查找m。
1 // File Name: 2976.cpp 2 // Author: Missa 3 // Created Time: 2013/3/16 星期六 15:37:33 4 5 #include<iostream> 6 #include<cstdio> 7 #include<cstring> 8 #include<algorithm> 9 #include<cmath> 10 #include<queue> 11 #include<stack> 12 #include<string> 13 #include<vector> 14 #include<cstdlib> 15 #include<map> 16 #include<set> 17 using namespace std; 18 #define CL(x,v) memset(x,v,sizeof(x)); 19 #define R(i,st,en) for(int i=st;i<en;i++) 20 #define ll long long 21 #define inf 0x3f3f3f3f 22 23 const int maxn = 1e3+5; 24 int n,k; 25 struct node 26 { 27 double a,b,c; 28 }p[maxn]; 29 bool cmp(const node &aa,const node &bb) 30 { 31 return aa.c>bb.c; 32 } 33 bool check(double m) 34 { 35 R(i,0,n) 36 p[i].c=p[i].a-p[i].b*m; 37 sort(p,p+n,cmp); 38 //R(i,0,n) 39 // printf("%lf %lf %lf\n",p[i].a,p[i].b,p[i].c); 40 //printf("\n"); 41 double ans=0.0; 42 R(i,0,n-k) 43 ans+=p[i].c; 44 if(ans<0.0) 45 return false; 46 else 47 return true; 48 } 49 int main() 50 { 51 while(~scanf("%d%d",&n,&k)) 52 { 53 if(!n && !k) break; 54 R(i,0,n) 55 scanf("%lf",&p[i].a); 56 R(i,0,n) 57 scanf("%lf",&p[i].b); 58 double low=0.0,high=1.0; 59 double mid; 60 while(high-low>1e-8) 61 { 62 mid=(high+low)/2.0; 63 //cout<<mid<<endl; 64 if(check(mid)) 65 low=mid; 66 else 67 high=mid; 68 } 69 printf("%.0f\n",100*mid); 70 } 71 return 0; 72 }