0-1背包问题DP表格法容量离散化原因及相关场景疑问
0-1背包问题DP实现的常见疑问解答
原实现代码
# A Dynamic Programming based Python # Program for 0-1 Knapsack problem # Returns the maximum value that can # be put in a knapsack of capacity W def knapSack(W, wt, val, n): K = [[0 for x in range(W + 1)] for x in range(n + 1)] # Build table K[][] in bottom up manner for i in range(n + 1): for w in range(W + 1): if i == 0 or w == 0: K[i][w] = 0 elif wt[i-1] <= w: K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]], K[i-1][w]) else: K[i][w] = K[i-1][w] return K[n][W] # Driver program to test above function val = [60, 100, 120] wt = [10, 20, 30] W = 50 n = len(val) print(knapSack(W, wt, val, n)) # This code is contributed by Bhavya Jain
疑问解答
1. 为何以1为单位离散化容量W,构建n×(W+1)的矩阵?
这个矩阵是DP的状态表,其中K[i][w]的含义是:考虑前i个物品时,背包容量为w能装下的最大价值。离散化容量是因为DP的核心是拆解问题为子问题——每个整数容量w对应一个独立的子问题,通过从小到大计算每个子问题的解,最终推导得到原问题(容量W)的答案。这种“自底向上”的方式能避免重复计算,是0-1背包最基础的DP实现思路。
2. 为何选择1作为离散单位?
选1作为离散单位是因为常规教学场景中的背包问题,物品重量和背包容量都是整数,1是最小的整数单位,用它离散化能覆盖所有可能的整数容量子问题,逻辑最简单、最直观,容易理解和实现。这也是大部分入门教程都采用这种方式的原因。
3. 若W极大(例如10000000000),矩阵是否会出现内存溢出?该怎么处理?
肯定会内存溢出。比如W=1e10时,光一维数组就需要1e10+1个元素,内存根本装不下。这时候要换用基于价值的DP思路:
- 重新定义状态:
dp[v]表示达到价值v所需的最小重量 - 初始化
dp[0] = 0,其余为无穷大 - 遍历每个物品,倒序更新
dp数组:对于每个v从总价值到当前物品价值,dp[v] = min(dp[v], dp[v - val[i]] + wt[i]) - 最后找到最大的
v,使得dp[v] <= W,这个v就是最大价值
这种方法的时间空间复杂度和总价值相关,适合W极大但总价值不大的场景。如果W和总价值都极大,只能用近似算法或分支定界法来求解。
4. 若容量W为小数(例如50.6)又该如何处理?
最实用的方法是把所有重量和容量转换为整数:
- 找到所有重量和W的小数位数的最大值,比如W=50.6(1位小数),物品重量如果是10.2、20.4这类,就把所有数乘以10,转成整数506、102、204
- 然后用整数版的DP代码计算,最终结果和原问题一致
- 如果小数是无理数或精度难以处理,也可以尝试浮点DP,但要注意精度误差问题,实际场景中这种情况很少见。
内容的提问来源于stack exchange,提问作者TSR
相关产品推荐
相关产品推荐

