背包问题
背包问题
问题描述
给定一组物品,每种物品都有自己的重量和价值,背包的容量为 W,如何选择物品,使得背包中物品的总价值最大?
问题分析
这是一个典型的动态规划问题,我们可以用二维数组 dp[i][j] 表示前 i 个物品恰好装入一个容量为 j 的背包可以获得的最大价值。
v[i] 表示第 i 个物品的价值,w[i] 表示第 i 个物品的重量。
边界条件:dp[i][j] = 0,i=0 or j=0。
状态转移方程如下:
1 | dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]) |
解释:
- 如果不放第 i 个物品,那么前 i-1 个物品恰好装入一个容量为 j 的背包可以获得的最大价值是 dp[i-1][j];
- 如果放第 i 个物品,那么前 i-1 个物品恰好装入一个容量为 j-w[i] 的背包可以获得的最大价值是 dp[i-1][j-w[i]],加上第 i 个物品的价值 v[i] 就是第 i 个物品恰好装入一个容量为 j 的背包可以获得的最大价值。
代码实现
1 | def pachage_problem(W, w, v): |
复杂度分析
时间复杂度:$O(nW)$,其中 n 是物品的个数,W 是背包的容量。
空间复杂度:$O(nW)$,需要创建一个 nW 大小的二维数组。
应用
- 0-1 背包问题:给定一组物品,每种物品都有自己的价值,背包的容量为 W,如何选择物品,使得背包中物品的总价值最大?
- 完全背包问题:给定一组物品,每种物品都有自己的价值和容量,如何选择物品,使得背包中物品的总价值最大?
- 多重背包问题:给定 n 件物品,每件物品都有自己的价值和容量,以及 m 个背包,如何选择物品,使得每个背包中物品的总价值最大?
扩展
完全背包问题
每种物品的数量是无限的,完全背包其实可以转换成0/1背包,第i种物品的出现次数至多是背包容量m/物品i重量w[i]。
多重背包问题
直接转换为0-1背包问题效率较低,为了优化,可以使用二进制分解的技巧,将每个物品的数量k[i]分解成若干份。二进制分解的优势在于它可以将原本k[i]的复杂度从$O(k[i])$降低到$O(log(k[i]))$。具体方法是将k[i]进行二进制拆分,比如k[i] = 13,可以拆分成1, 2, 4, 6,使复杂度降低。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 麦克罗的思维天地!
评论


