POJ2976 Dropping tests

辣鸡POJ输出只能写%.0f

今天做bz时扫到了01分数规划,就来写一写

式子就是R=sigma(a[i]*x[i])/sigma(b[i]*x[i])

我们先定义一个函数F(L):=sigma(a[i]*x[i])-L*sigma(b[i]*x[i]),显然这只是对目标式的一个简单的变形。分离参数,得到F(L):=sigma((a[i]-L*b[i])*x[i])。这时我们就会发现,如果L已知的话,a[i]-L*b[i]就是已知的,当然x[i]是未知的。记d[i]=a[i]-L*b[i],那么F(L):=sigma(d[i]*x[i]),多么简洁的式子。我们就对这些东西下手了。

如果F[L]>0,这样也就是sigma(a[i]*x[i])/sigma(b[i]*x[i])>L,也就是一定有解比当前优,这是我们想要的,所以我们二分一个答案,就是L,这样我们可以求出F(L),题目中说要n-k个,那么我们贪心的取最大就可以使答案最优。

所以直到F[L]==0,R取得最大值。

By:大奕哥

 1 #include<cmath>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 using namespace std;
10 double a[1005],b[1005],t[1005],sum,eps=1e-7;
11 int n,k;
12 int main()
13 {
14     while(~scanf("%d%d",&n,&k))
15     {
16         if(!n&&!k)break;double l=0,r=1;
17         for(int i=1;i<=n;++i)scanf("%lf",&a[i]);
18         for(int i=1;i<=n;++i)scanf("%lf",&b[i]);
19         while(r-l>=eps)
20         {
21             double mid=(l+r)/2;sum=0;
22             for(int i=1;i<=n;++i)
23             {
24                 t[i]=a[i]-mid*b[i];
25             }
26             sort(t+1,t+1+n);
27             for(int i=k+1;i<=n;++i)
28             {
29                 sum+=t[i];
30             }
31             if(sum>0)l=mid;
32             else r=mid;
33         }
34         printf("%.0f\n",l*100);
35     }
36     return 0;
37 }

 

posted @ 2018-01-19 15:19  大奕哥&VANE  阅读(138)  评论(0编辑  收藏  举报