• [USACO18OPEN]Talent Show


    [USACO18OPEN]Talent Show

    有N对数({w_i})({t_i}),选出几对数,使(w_i)之和大于W,并且使t之和除以w之和乘以1000尽可能大,(1≤N≤250,1≤W≤1000)

    显然为分数规划,于是写出二分式(sum x_i(t_i-w_is)),现在问题在于如何选出括号里最大的数,并且使它们的(w_i)之和大于W,自然为一最优化问题,考虑递推,但是注意到题目很像背包,于是按照01背包的办法就可以求出最优解,注意边界所以要初始化无限小,其他照01分数规划的套路即可。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    #define exact 0.000001
    using namespace std;
    int a[251],b[251],n,w;
    double c[251],dp[1001];
    il bool check(double);
    il double dfs(double,double);
    template<class free>il free Max(free,free);
    int main(){
        int i;scanf("%d%d",&n,&w);
        for(i=1;i<=n;++i)
            scanf("%d%d",&b[i],&a[i]),a[i]*=1000;
        printf("%.0lf",dfs(0,250000)-0.5);
        return 0;
    }
    template<class free>
    il free Max(free a,free b){
        return a>b?a:b;
    }
    il bool check(double x){
        int i,j;
        for(i=1;i<=w;++i)dp[i]=-1e19;
        for(i=1;i<=n;++i){
            c[i]=a[i]-b[i]*x;
            for(j=w;j>=w-b[i]&&j>=0;--j)
                dp[w]=Max(dp[w],dp[j]+c[i]);
            for(j=w;j>=b[i];--j)
                dp[j]=Max(dp[j-b[i]]+c[i],dp[j]);
        }return dp[w]>exact;
    }
    il double dfs(double l,double r){
        double mid;
        while(l+exact<r){
            mid=(l+r)/2;
            if(check(mid))l=mid+exact;
            else r=mid-exact;
        }return (l+r)/2;
    }
    
    
  • 相关阅读:
    Ruby--Array
    SQL--查询相同字段的数据
    Ruby--CSV
    Ruby--String
    Git常用命令
    JS Date函数操作
    FTP命令
    Rails--%w用法[转]
    Rails--export csv
    Mysql远程访问
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10804880.html
Copyright © 2020-2023  润新知