题解 [USACO18OPEN] Talent Show 01分数规划

题解 [USACO18OPEN] Talent Show

题目描述

题目描述网上有。

具体做法

01分数规划入门题!

考虑我们为每个数设一个 x i x_i xi, x i x_i xi只有 0 , 1 0,1 0,1两种取值。

那么题目要求的式子为:
∑ i = 1 n t i x i w i x i \sum_{i=1}^{n}{\frac{t_ix_i}{w_ix_i}} i=1nwixitixi
相当于我们要求解每个 x i x_i xi的取值,同时满足 ∑ i = 1 n w i x i ≥ W \sum_{i=1}^{n}{w_ix_i} \geq W i=1nwixiW

考虑二分答案 m i d mid mid

式子变成:
∑ i = 1 n t i x i w i x i ≥ m i d \sum_{i=1}^{n}{\frac{t_ix_i}{w_ix_i}} \geq mid i=1nwixitiximid
移项后变成
∑ i = 1 n x i ( t i − w i m i d ) ≥ 0 \sum_{i=1}^{n}{x_i(t_i-w_imid)} \ge 0 i=1nxi(tiwimid)0
t i − w i m i d t_i-w_imid tiwimid看成 v a l i val_i vali,那么就可以做一个简单背包来判断了。

C o d e \mathcal{Code} Code

/*******************************
Author:galaxy yr
LANG:C++
Created Time:2019年10月27日 星期日 21时56分52秒
*******************************/
#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;

struct IO{
    template<typename T>
    IO & operator>>(T&res)
    {
        T q=1;char ch;
        while((ch=getchar())<'0' or ch>'9')if(ch=='-')q=-q;
        res=(ch^48);
        while((ch=getchar())>='0' and ch<='9') res=(res<<1)+(res<<3)+(ch^48);
        res*=q;
        return *this;
    }
}cin;

const int maxn=255;
const double eps=1e-4;
int n,W,w[maxn],t[maxn];
double val[maxn],f[10000];
double ans;

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

int main()
{
    //freopen("p4377.in","r",stdin);
    //freopen("p4377.out","w",stdout);
    cin>>n>>W;
    for(int i=1;i<=n;i++)
        cin>>w[i]>>t[i];
    double l=0,r=1e9,mid;
    while((r-l)>eps)
    {
        mid=(l+r)/2;
        if(check(mid))
            l=mid,ans=mid;
        else
            r=mid;
    }
    int res=(int)(ans*1000);
    printf("%d\n",res);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值