问题:
背包最大容量为4,物品如下,问背包能背的物品最大价值为多少?
背包问题关键就在于:对于每个物品,放还是不放,带着这个思想去理解递推公式就很容易了,下面是代码:
def bag_2Dim(): # 01背包的二维dp解法
# dp[i][j]表示从下标为[0-i]的物品⾥任意取,放进容量为j的背包,价值总和最⼤是多少
m = 3 # 物品数量
n = 4 # 背包最大容量
weight = [1, 3, 4]
value = [15, 20, 30]
# m = int(input()) # ACM输入模式
# n = int(input())
# weight = list(map(int, input().split()))
# value = list(map(int, input().split()))
dp = [[0] * (n+1) for _ in range(m)]
# 初始化状态
for i in range(m):
dp[i][0] = 0 # 背包容量为0时,最大价值一定为0
for j in range(n+1): # 不同背包容量下装第0个物品的最大价值
if j < weight[0]:
dp[0][j] = 0
else:
dp[0][j] = value[0]
# print(dp)
for i in range(1, m): # 先物品
for j in range(1, n+1): # 后正序背包
dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i]] + value[i])
return dp[m-1][n]
二维解法比较基础,可以将状态压缩,只留背包容量这一状态。
def bag_1Dim(): # 01背包的一维dp解法
# dp[j]表示容量为j的背包,所背物品的最大价值价值
m = 3 # 物品数量
n = 4 # 背包最大容量
weight = [1, 3, 4]
value = [15, 20, 30]
dp = [0] * (n+1)
for i in range(m): # 先物品
for j in range(n, -1, -1): # 后倒序背包
if j >= weight[i]: # 只有能装下该物品时才能操作
dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
return max(dp)
注意一维dp解法中,遍历背包顺序是从大到小倒序遍历,因为如果从小到大遍历的话,每次取得的状态会和之前取得的状态重合,每个物品被放入了不止一次。如果是完全背包问题(每件物品有无限个),就得从小到大遍历了,也就是每个物品可以放入背包多次。