題解 [USACO18OPEN] Talent Show 01分數規劃

題解 [USACO18OPEN] Talent Show

題目描述

題目描述網上有。

具體做法

01分數規劃入門題!

考慮我們爲每個數設一個xix_i,xix_i只有0,10,1兩種取值。

那麼題目要求的式子爲:
i=1ntixiwixi \sum_{i=1}^{n}{\frac{t_ix_i}{w_ix_i}}
相當於我們要求解每個xix_i的取值,同時滿足i=1nwixiW\sum_{i=1}^{n}{w_ix_i} \geq W

考慮二分答案midmid

式子變成:
i=1ntixiwiximid \sum_{i=1}^{n}{\frac{t_ix_i}{w_ix_i}} \geq mid
移項後變成
i=1nxi(tiwimid)0 \sum_{i=1}^{n}{x_i(t_i-w_imid)} \ge 0
tiwimidt_i-w_imid看成valival_i,那麼就可以做一個簡單揹包來判斷了。

Code\mathcal{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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章