问题描述
01背包问题可描述为如下问题:
有一个容量为V的背包,还有n个物体。现在忽略物体实际几何形状,我们认为只要背包的剩余容量大于等于物体体积,那就可以装进背包里。每个物体都有两个属性,即体积w和价值v。
问:如何向背包装物体才能使背包中物体的总价值最大?
问题描述
利用局部最优逐步推导去全局最优
当背包容量为6的时候不放西瓜时的最大价值为8
当放入西瓜后,背包还剩下容量2。后续只能在背包容量为2的情况下找到能装的最大值为6+3
伪代码
***
dp[i][j]:编号为0-i之间的物品,任取放在容量为j的背包里
递推表达式:不放物品i data1 = dp[i-1][j]
放物品i data2 = dp[i-1][j-weight[i]] + value[i];
dp[i][j] = max(data1,data2)
初始化:第一列背包容量为0,直接初始化为0
第一行:if(j >= weight[0]) dp[0][j] = value[0]
遍历顺序:从左向右,从上到下
***
for i in range(1,物品+1):
for j in range(1,容量+1):
if(j < 物品i.weight:
dp[i][j] = dp[i-1][j]
else:
data1 = dp[i-1][j] #不装入物品i
data2 = dp[i-1][j-物品i.weight] + 物品i.value #装入物品i
dp[i][j] = max(data1,data2)
解法2:使用滚动数组
使用一维滚动数组:每次计算完就讲上层的计算结果拷贝下来
dp[j]:容量为j的背包所能装的最大价值
递推公式:不放物品i data1 = dp[j]
放物品i data2 = dp[j-weight[i]] + value[i]
dp[j] = max(data1,data2)
初始化:dp[i] = 0
遍历顺序:for(i=0;i<物品数量;i++) 物品
for(j=bagweight;j>=weight[i];j--) 背包
递推公式
为什么要倒序遍历背包:正序遍历会多次放同一个物品
正序:dp[1] = dp[1-1] + 15 = 15
dp[2] = dp[2-1] + 15 = 30 可以看到第一个物品被放了两次
倒序:dp[2] = dp[2-1] + 15 = 15
dp[1] = dp[1-1] + 15 = 15