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 }

 

你可能感兴趣的:(poj)