淬炼神体

来源:互联网 发布:mac日本官网 编辑:程序博客网 时间:2024/05/16 10:40

题目大意

有N个东西,选择第i个东西价值为a[i],付出为b[i]。需要选择恰好M个东西来最大化a[i]/b[i]
N<=10^5。结果保留三位小数。

01分数规划

如果a[i]/b[i]=c
a[i]=b[i]c
(a[i]b[i]c)=0
因此我们可以设d[i]=a[i]-b[i]*c。c是不确定,不过发现c就是答案。因此我们二分c并计算d数组,由于结果大于等于0就代表这个答案是可行的,因此我们对d数组排序然后取前M个检验是否大于等于0。

注意

因为要保留三位小数,所以应当精确到四位,然后四舍五入。

参考程序

#include<cstdio>#include<cmath>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef double db;const int maxn=100000+10;db d[maxn],a[maxn],b[maxn];db p,l,r,mid,ans;int i,j,k,t,n,m;bool cmp(db a,db b){    return a>b;}int main(){    scanf("%d%d",&n,&m);    fo(i,1,n) scanf("%lf",&a[i]);    fo(i,1,n) scanf("%lf",&b[i]);    j=1;    fo(i,2,n)        if (a[i]/b[i]>a[j]/b[j]) j=i;    l=0;r=a[j]/b[j];    while (abs(r-l)>=0.0001){        mid=(l+r+0.0001)/2;        fo(i,1,n) d[i]=a[i]-mid*b[i];        sort(d+1,d+n+1,cmp);        p=0;        fo(i,1,m) p=p+d[i];        if (p>=0) l=mid;else r=mid-0.0001;    }    printf("%.3lf\n",l);    return 0;}
0 0
原创粉丝点击