0
点赞
收藏
分享

微信扫一扫

动态规划背包问题——完全背包

waaagh 2022-06-17 阅读 55

问题描述:
有n种物品,每种均有无穷多个。第i个物品的体积为vi,重量为wi。选一些物品装到容量为C的背包中,使得背包内物品在总体积不超过C的前提下重量尽量大。

问题分析:
开一个数组f[i][j]表示前i种物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大重量。
每种物品无穷个,所以还要有一个k遍历从0到“最大”。
f[i][j]=max(f[i][j],f[i-1][j-kv[i]]+kw[i]);
注意一下,01背包是f[i][j]=max(f[i-1][j], f[i-1][j-v[i]]+w[i]);max中第一项是f[i-1][j],而这里确是f[i][j],为什么呢?想一下,当k=0时(也就是k刚开始遍历),f[i][j]是0,max右项就是f[i-1][j]。被包含进来了,而且k的遍历中,每次还要对f[i][j]进行更新,所以这里是f[i][j]而不是f[i-1][j]。

代码:

memset(f, 0, sizeof(f));
for (int i=1; i<=n; i++){
for (int j=0; j<=c; j++){
for (int k=0; k*v[i]<=j; k++){
f[i][j]=max(f[i][j], f[i-1][j-k*v[i]]+k*w[i]);
}
}
}

优化:
将原始算法的DP思想转变一下。
设f[i][j]表示出在前i种物品中选取若干件物品放入容量为j的背包所得的最大重量。那么对于第i种物品的出现,我们对第i种物品放不放入背包进行决策。
如果不放那么f[i][j]=f[i-1][j];如果确定放,背包中应该出现至少一件第i种物品,所以f[i][j]中至少应该出现一件第i种物品,即f[i][j]=f[i][j-v[i]]+w[i]。
为什么会是f[i][j-v[i]]+w[i]?因为我们前面已经最大限度的放了第i件物品,如果能放就放这最后的一件,(或者理解为前面已经往背包中放入了第i件物品,我们每一次只增加一件的往背包里放,而且只能增加一件,多了放不下)。

代码:

memset(f, 0, sizeof(f));
for (int i=1; i<=n; i++){
for (int j=0; j<=c; j++){
if (j>=v[i])
f[i][j]=max(f[i-1][j], f[i][j-v[i]]+w[i]);//01背包为:max(f[i-1][j], f[i-1][j-v[i]]+w[i]);
else
f[i][j]=f[i-1][j];
}
}

附滚动数组优化:

for (int i=1; i<=n; i++){
int a, b;
cin>>a>>b;
for (int j=0; j<=v; j++){//注意这里变成了从左到右
if (j>=a)
f[j]=max(f[j], f[j-a]+b);
}
}

参考链接:​​https://www.statusrank.xyz/​​

举报

相关推荐

0 条评论