bzoj 5281: [Usaco2018 Open]Talent Show【dp】

注意到sum_t比较小,所以设f[i][j]为选前i头牛,当前sum_t为j的最小sum_w值,转移是f[i][j]=min(f[i-1][j],f[i-1][j-t[i]]+w[i]),然后i维用滚动数组优化即可
注意j<t[i]的部分也要赋值成f[i-1][j]……

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=255;
int n,m,f[2][250005],w[N],t[N],sm;
long long ans=-1e18;
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>'9'||p<'0')
    {
        if(p=='-')
            f=-1;
        p=getchar();
    }
    while(p>='0'&&p<='9')
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        w[i]=read(),t[i]=read(),sm+=t[i];
    memset(f,0x3f,sizeof(f));
    f[0][0]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<t[i];j++)
            f[i&1][j]=f[~i&1][j];
        for(int j=t[i];j<=sm;j++)
            f[i&1][j]=min(f[~i&1][j],f[~i&1][j-t[i]]+w[i]);//,cerr<<i-1<<" "<<j<<" "<<i<<" "<<j<<" "<<f[i&1][j]<<endl;
    }
    for(int i=1;i<=sm;i++)
        if(f[n&1][i]>=m)
            ans=max(ans,(long long)((double)(1ll*i*1000)/(double)f[n&1][i]));
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lokiii/p/9660487.html
今日推荐