codevs 5429 完全背包

Posted on 2016-11-11 20:22  ziliuziliu  阅读(300)  评论(0编辑  收藏  举报

单调队列优化。

好像有点烦。。。调了许久。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 7050
using namespace std;
long long n,m,v[maxn],w[maxn],c[maxn],up[maxn],q[maxn],l,r,ret1,ret2,val[maxn],dp[maxn];
void get_up(long long x)
{
    for (long long i=0;i<=m%v[x];i++)
        up[i]=(m/v[x])*v[x]+i;
    for (long long i=m%v[x]+1;i<=v[x]-1;i++)
        up[i]=(m/v[x]-1)*v[x]+i;
}
void insert(long long x,long long y,long long z)
{
    while ((l<=r) && (val[r]<=dp[x]-y*w[z])) r--;
    q[++r]=x;val[r]=dp[x]-y*w[z];
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for (long long i=1;i<=n;i++)
        scanf("%lld%lld%lld",&v[i],&w[i],&c[i]);
    for (long long i=1;i<=n;i++)
    {
        get_up(i);
        for (long long j=0;j<v[i];j++)
        {
            l=1;r=0;long long now=up[j],lim=up[j];ret1=ret2=up[j]/v[i];
            while (now>=0)
            {
                while ((l<=r) && (q[l]>now)) l++;
                while ((lim>=now-c[i]*v[i]) && (lim>=0))
                {
                    insert(lim,ret2,i);
                    lim-=v[i];ret2--;
                }
                dp[now]=val[l]+ret1*w[i];ret1--;now-=v[i];
            }
        }        
    }
    printf("%lld\n",dp[m]);
    return 0;
}