[BZOJ5281][Usaco2018 Open]Talent Show:0/1分数规划+背包DP

分析:

二分答案后利用0/1背包检查合法性即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>

const int MAXN=255;
int n,W;
int w[MAXN],t[MAXN];
double c[MAXN],f[1005];

inline bool check(double mid){
    for(int i=1;i<=n;i++) c[i]=t[i]-w[i]*mid;
    for(int i=0;i<=W;i++) f[i]=-1e9;f[0]=0;
    for(int i=1;i<=n;i++){
        for(int j=W;j+w[i]>=W&&j+1;j--) f[W]=std::max(f[W],f[j]+c[i]);
        for(int j=W-1;j;j--) if(j>=w[i]) f[j]=std::max(f[j],f[j-w[i]]+c[i]);
    }
    return f[W]>=0;
}

int main(){
    scanf("%d%d",&n,&W);
    for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&t[i]);
    double l=0,r=1e6+5,ans;
    while(r-l>1e-8){
        double mid=(l+r)/2;
        if(check(mid)) ans=mid,l=mid;
        else r=mid;
    }
    printf("%.0lf\n",floor(ans*1000));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9690997.html
今日推荐