背包问题
初始值
物品重量 w = [3, 4, 5, 7]
物品价值 v = [1, 5, 6, 9]
物品数量 n = 4
背包容量 c = 10
01背包
ans = 11
递归求解
递归思路
背包容量剩余 cnt 的情况下, 在第 i 个及以后物品里装最大价值的东西
def backbag(i, cnt):
if i == n or cnt == 0: # 没有物品可供选择或者背包容量为0, 能装的东西的价值为 0
return 0
if w[i] <= cnt: # 当前物品的重量低于背包容量, 可以考虑装还是不装
yes = backbag(i+1, cnt - w[i]) + v[i] # 将第 i 号物品装入背包
no = backbag(i + 1, cnt) # 不装入第 i 号物品
return max(yes, no) # 取其中的较大值
else: # 无法装入,继续选择后面的物品
return backbag(i + 1, cnt)
print(backbag(0, c)) # 初始从第一个物品开始选择, 背包容量为 c
输出结果为 11
动态规划求解
w.insert(0, 0)
v.insert(0, 0) # 让行标与物品索引能一一对应
dp = [[0] * (c + 1) for i in range(n + 1)]
for i in range(1,n+1):
for j in range(c + 1):
if w[i] <= j: # 可以放入, 比较放入此物品与不放入此物品的最大价值,去较大值
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i])
else: # 不能放入, 则继承值
dp[i][j] = dp[i - 1][j]
print(dp[-1][-1]) # 输出结果
完全背包
递归解法
递归思路:如果能装入, 则将其装入,并且是在当前行的基础上处理
递归解法很好用, 但是难理解一些
w = [3, 4, 5, 7]
v = [1, 5, 6, 9]
n = 4
c = 10
def fun(i, cnt):
if i == n or cnt == 0:
return 0
if cnt >= w[i]:
return max(fun(i + 1, cnt), fun(i, cnt - w[i]) + v[i])
# 不装入此物品 与 在当前物品的情况下, 继续装入此物品的较大的值
else:
return fun(i + 1, cnt) # 无法装入, 进入下一个物品的递归
print(fun(0, c)) # 最后返回的是一个数。
动态规划求解
w.insert(0, 0)
v.insert(0, 0) # 让行标与物品索引能一一对应
dp = [[0] * (c + 1) for i in range(n + 1)]
for i in range(1,n+1):
for j in range(c + 1):
if w[i] <= j: # 可以放入, 在左侧与上方结果中选择最大值
dp[i][j] = max(dp[i - 1][j], dp[i][j - w[i]] + v[i])
else: # 不能放入, 则继承值
dp[i][j] = dp[i - 1][j]
print(dp[-1][-1])
01背包与完全背包动态规划的唯一区别: 在上一行的基础上推导 vs 在当前行基础上推导
多重背包问题
多重背包的问题, 可以转化为01背包问题来求解