背包问题规律总结
注意点:搞不清楚就写出dp数组 | ||
01背包问题,选不选该种物品`` |
for i in range(1,len(nums)+1):
for j in range(W+1):
if j>=w[i]:
dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
else:
dp[i][j] = dp[i-1][j]
压缩数组后
由于dp[i][j]需要dp[i-1][j]的数据,dp[i-1][j]不可被覆盖,如果从后往前遍历的话,dp[i-1][j]不会被覆盖
for i in range(len(nums)):
for j in range(W,-1,-1):
if j>=w[i]:
dp[j] = max(dp[j],dp[j-w[i]]+v[i])
完全背包问题:
简单思路(也是处理多重背包的思路,将W//(w[i])改为多重背包的上限即可),将其转化为01背包问题,给物品属性加倍作为新的物品,要求不超过总重量
for i in range(len(nums)):
for j in range(W,-1,-1):
for k in range(1,W//(w[i])):
dp[j] += dp[j-k*w[i]]
优化思路,选不选取该个物品
dp[i][j] = dp[i-1][j] + dp[i][j-w[i]]
压缩数组后,由于dp[i][j-w[i]]需要被覆盖,dp[i-1][j]不可被覆盖,如果从前往后遍历刚好可以满足上述要求
for i in range(len(nums)):
for j in range(1,W+1):
if j-w[i]>=0:
dp[j] += dp[j-w[i]]
有序完全背包问题:
以组合中最后一个选中的数字为准,即可满足有序条件,所以需要将重量的循环拿到外边
for j in range(1,W+1):
for i in range(len(nums)):
if j-w[i]>=0:
dp[j] += dp[j-w[i]]