题意:有n场考试,给出每场答对的题数a和这场一共有几道题b,求去掉k场考试后,公式.的最大值
解题关键:01分数规划,double类型二分的写法(poj崩溃,未提交)
或者r-l<=1e-3(右边是精度)
为什么v-xw>=0?(v/x>=x?)
ans要求的是最大值,我们定义:c(x)可以选择使得单位重量的价值>=x,最大值一定满足此函数,此函数关于x单调递减,可以求得一个最大值。求得的x的最大值即是ans。
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> #define maxn 1006 #define eps 1e-8 #define inf 0x3f3f3f3f using namespace std; typedef long long ll; int n,k; double ans; struct node{ double a,b; }num[maxn]; bool cmp(const node &x,const node &y){ return x.a-x.b*ans>=y.a-y.b*ans; } bool check(double x){ ans=x; sort(num+1,num+n+1,cmp); double sum=0; for(int i=1;i<=n-k;i++) sum+=num[i].a-x*num[i].b; return sum>=-eps; } double erfen(double l,double r){ while(r-l>eps){//for(int i=1;i<=100;i++) double mid=(l+r)/2; if(check(mid)) l=mid; else r=mid; } return r; } int main(){ while(scanf("%d%d",&n,&k)!=EOF&&(n||k)){ for(int i=1;i<=n;i++) scanf("%lf",&num[i].a); for(int i=1;i<=n;i++) scanf("%lf",&num[i].b); double ans=erfen(0,1.0*inf); printf("%.0lf ",100*ans);//必须四舍五入 //printf("%d ",(int)(100*ans+0.5)); } return 0; }
2、Dinkelbach算法(原理上比二分更快,因为利用了当前直线所对应的解)
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> #define eps 1e-8 using namespace std; typedef long long ll; double a[1010],b[1010]; struct node{ double num; int ord; }d[1010]; bool cmp(node a,node b){ return a.num>b.num; } int main(){ int n,k; while(scanf("%d%d",&n,&k)&&(n||k)){ for(int i=0;i<n;i++)scanf("%lf",&a[i]); for(int i=0;i<n;i++)scanf("%lf",&b[i]); double l=0.0,ans; while(1){ ans=l; for(int i=0;i<n;i++){ d[i].num=a[i]-ans*b[i]; d[i].ord=i; } sort(d,d+n,cmp); double p=0.0,q=0.0; for(int i=0;i<n-k;i++){ p+=a[d[i].ord]; q+=b[d[i].ord]; } l=p/q; if(fabs(ans-l)<eps) break; } if(ans>1)ans=1; if(ans<0)ans=0; printf("%.0f ",100*ans); } return 0; }