本文搬运自本人初中博客园博客,若图片加载不出来,可到原文查看:https://www.cnblogs.com/zhangtingxi/p/16576747.html

普通多重背包

外层枚举哪个包,中层枚举容量,内存枚举数量

1
2
3
4
for(i=1; i<=n; ++i)
for(j=m; j>=0; --j)
for(k=1; k*w[i]<=j && j<=s[i]; ++k)
f[j]=max(f[j], f[j-k*w[i]]+k*v[i]);

二进制优化

相当于把每个包拆成 loglog 个包然后分别01背包

1
2
3
4
5
6
7
8
9
for(i=1; i<=n; ++i)
{
cin>>v[i]>>w[i]>>s[i];
for(j=1; j<=s[i]; j<<=1)
a[++k].v=v[i]*j, a[k].w=w[i]*j, s[i]-=j;
if(s[i]) a[++k].v=v[i]*s[i], a[k].w=w[i]*s[i];
}

for(...) //对a进行01背包

单调队列优化

相当于完全背包,但太久之前的要pop掉

1
2
3
4
5
6
7
8
9
10
11
for(i=1; i<=n; ++i)
{
for(j=0; j<w[i]; ++j) l[j]=0, q[j][r[j]=1]=f[j], z[j][1]=0;
for(j=w[i]; j<=m; ++j)
{
while(l[j%w[i]]<r[j%w[i]] && j/w[i]-z[j%w[i]][l[j%w[i]]+1]>s[i]) ++l[j%w[i]];
f[j]=max(f[j%w[i]], q[j][l[j]+1]+v[i]);
while((l[j%w[i]]<r[j%w[i]] && f[j]>q[j%w[i][r[j%w[i]]]]) --r[j%w[i]];
q[j%w[i]][++r[j%w[i]]]=f[j]; z[j%w[i]][r[j%w[i]]]=j/w[i];
}
}

没调过,不知道有没有打错