5. 混合背包问题

混合背包问题:有 n 种物品和一个最多能装重量为 W 的背包,第 i 种物品的重量为 weight[i],价值为 value[i],件数为 count[i]。其中:

  1. 当 count[i]=−1 时,代表该物品只有 1 件。
  2. 当 count[i]=0 时,代表该物品有无限件。
  3. 当 count[i]>0 时,代表该物品有 count[i] 件。

请问在总重量不超过背包载重上限的情况下,能装入背包的最大价值是多少?

img

思路 1:动态规划

混合背包问题其实就是将「0-1 背包问题」、「完全背包问题」和「多重背包问题」这 3 种背包问题综合起来,有的是能取 1 件,有的能取无数件,有的只能取 count[i] 件。

其实只要理解了之前讲解的这 3 种背包问题的核心思想,只要将其合并在一起就可以了。

并且在「多重背包问题」中,我们曾经使用「二进制优化」的方式,将「多重背包问题」转换为「0-1 背包问题」,那么在解决「混合背包问题」时,我们也可以先将「多重背包问题」转换为「0-1 背包问题」,然后直接再区分是「0-1 背包问题」还是「完全背包问题」就可以了。

思路 1:代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Solution:
def mixedPackMethod1(self, weight: [int], value: [int], count: [int], W: int):
weight_new, value_new, count_new = [], [], []

# 二进制优化
for i in range(len(weight)):
cnt = count[i]
# 多重背包问题,转为 0-1 背包问题
if cnt > 0:
k = 1
while k <= cnt:
cnt -= k
weight_new.append(weight[i] * k)
value_new.append(value[i] * k)
count_new.append(1)
k *= 2
if cnt > 0:
weight_new.append(weight[i] * cnt)
value_new.append(value[i] * cnt)
count_new.append(1)
# 0-1 背包问题,直接添加
elif cnt == -1:
weight_new.append(weight[i])
value_new.append(value[i])
count_new.append(1)
# 完全背包问题,标记并添加
else:
weight_new.append(weight[i])
value_new.append(value[i])
count_new.append(0)

dp = [0 for _ in range(W + 1)]
size = len(weight_new)

# 枚举前 i 种物品
for i in range(1, size + 1):
# 0-1 背包问题
if count_new[i - 1] == 1:
# 逆序枚举背包装载重量(避免状态值错误)
for w in range(W, weight_new[i - 1] - 1, -1):
# dp[w] 取「前 i - 1 件物品装入载重为 w 的背包中的最大价值」与「前 i - 1 件物品装入载重为 w - weight_new[i - 1] 的背包中,再装入第 i - 1 物品所得的最大价值」两者中的最大值
dp[w] = max(dp[w], dp[w - weight_new[i - 1]] + value_new[i - 1])
# 完全背包问题
else:
# 正序枚举背包装载重量
for w in range(weight_new[i - 1], W + 1):
# dp[w] 取「前 i - 1 种物品装入载重为 w 的背包中的最大价值」与「前 i 种物品装入载重为 w - weight[i - 1] 的背包中,再装入 1 件第 i - 1 种物品所得的最大价值」两者中的最大值
dp[w] = max(dp[w], dp[w - weight_new[i - 1]] + value_new[i - 1])

return dp[W]

思路 1:复杂度分析

  • 时间复杂度:O(W×∑log⁡2count[i]),其中 W 为背包的载重上限,count[i] 是第 i 种物品的数量。
  • 空间复杂度:O(W)。

本站由 卡卡龙 使用 Stellar 1.27.0 主题创建

本站访问量 次. 本文阅读量 次.