完全背包
完全背包
此类背包问题中,我们的每种物品有无限多个,可重复选取。
类似于01背包,我们依旧需要考虑前i-1件物品的影响。
此时我们依旧可以设得二维状态
f[i][v]代表用i件物品填充为体积为v的背包得到的最大价值
依旧很容易写出状态转移方程
f[i][v]=max(f[i−1][v],f[i−1][j−k∗c[i]]+k∗w[i])
//其中k是我们需要枚举的物品件数。而我们最多选取V/c[i] 个
for(int i=1;i<=n;i++)//枚举物品
for(int j=1;j<=V;j++)
for(int k=1;k<=V/c[i];k++)//我们的物品最多只能放多少件。
{
if(k*c[i]<=j)
f[i][j]=max(f[i-1][j],f[i-1][j-k*c[i]]+k*w[i]);
else
f[i][j]=f[i-1][j];
//判断条件与01背包相同。
}
同样地,我们去考虑一维状态
依旧设
f[i]代表体积为i的时候所能得到的最大价值
与01背包不同的是,我们可以重复选取同一件物品。
此时,我们就需要考虑到前面i-1件物品中是否有已经选取过
即,我们当前选取的物品,可能之前已经选取过。我们需要考虑之前物品对答案的贡献。因此我们需要顺序枚举。
与01背包一维的写法类似。
代码写法
for(int i=1;i<=n;i++)//枚举物品
for(int j=c[i];j<=V;j++)//枚举体积。注意这里是顺序/
f[j]=max(f[j],f[j-c[i]]+w[i]);//状态转移。
小结
完全背包也是类似于01背包,应该也算上是它的一种变形。
比较一般的写法是一维写法,希望大家能掌握。
例题-->p1616 疯狂的采药