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 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。