码迷,mamicode.com
首页 > 其他好文 > 详细

单调队列优化多重背包

时间:2018-01-30 23:10:10      阅读:322      评论:0      收藏:0      [点我收藏+]

标签:多重背包   problem   多重   target   优化   names   背包   http   targe   

http://codevs.cn/problem/5429/

 

把背包体积按 模物品体积 分类

在每个剩余类中使用单调队列

 

具体点就是

设物品体积为v,价值为w,现在要计算体积模v=0时的价值

设f[i][j] 表示 前i个物品,体积为j时的最大价值

f[i][5v]=max{ f[i-1][4v]+w , f[i-1][3v]+2w , f[i-1][2v]+3w , f[i-1][v]+4w , f[i-1][0]+5w }

f[i][4v]=max{ f[i-1][3v]+w , f[i-1][2v]+2w , f[i-1][v]+3w , f[i-1][0]+4w }

对所有的f[i][j]-j/v*w

f[i][5v]=max{ f[i-1][4v]-4w , f[i-1][3v]-3w , f[i-1][2v]-2w , f[i-1][v]-w , f[i-1][0] }

f[i][4v]=max{                        f[i-1][3v]-3w , f[i-1][2v]-2w , f[i-1][v]-w , f[i-1][0] }

f[i][j]=max{f[i-1][j%v+k*v]-k*w}+j*w

当固定了j%v后,就可以使用单调队列优化了

 

 

#include<cstdio>

using namespace std;

int dp[7001];

int q[7001][2];

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int v,w,cnt;
    int h,t;
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d%d",&v,&w,&cnt);
        if(m/v<cnt) cnt=m/v;
        for(int j=0;j<v;++j)
        {
            h=0; t=0;
            for(int k=0;k<=(m-j)/v;++k)
            {
                while(h<t && dp[j+k*v]-k*w>q[t-1][0]) t--;
                while(h<t && q[h][1]+cnt<k) h++;
                q[t][0]=dp[j+k*v]-k*w;
                q[t++][1]=k;
                dp[j+k*v]=q[h][0]+k*w;
            }
        }
    }
    printf("%d",dp[m]);
}

 

单调队列优化多重背包

标签:多重背包   problem   多重   target   优化   names   背包   http   targe   

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8387269.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!