5. 混合背包问题
混合背包问题:有 n 种物品和一个最多能装重量为 W 的背包,第 i 种物品的重量为 weight[i],价值为 value[i],件数为 count[i]。其中:
- 当 count[i]=−1 时,代表该物品只有 1 件。
- 当 count[i]=0 时,代表该物品有无限件。
- 当 count[i]>0 时,代表该物品有 count[i] 件。
请问在总重量不超过背包载重上限的情况下,能装入背包的最大价值是多少?
思路 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] 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) 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) for i in range(1, size + 1): if count_new[i - 1] == 1: for w in range(W, weight_new[i - 1] - 1, -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] = max(dp[w], dp[w - weight_new[i - 1]] + value_new[i - 1]) return dp[W]
|
思路 1:复杂度分析
- 时间复杂度:O(W×∑log2count[i]),其中 W 为背包的载重上限,count[i] 是第 i 种物品的数量。
- 空间复杂度:O(W)。