01背包问题解决方案重量超容求助:调试整夜仍未排查出问题
最简背包问题重量超容的问题修复
问题根源
- taken数组判断逻辑完全错误:你当前通过对比最大容量下的价值变化来决定是否取物品,完全没考虑重量约束,这种判断方式只会看价值是否提升,根本不管加入物品后重量会不会超,必然导致总重量超标。
- 动态规划数组索引混乱:你创建的
knapsack[capacity][itemCount]数组索引对应关系错误,且循环中i从0开始时访问i-1会触发索引越界,导致初始状态就有问题。
修正后的代码
# 重新定义DP数组:dp[i][j] = 前i个物品、背包容量j时的最大价值 dp = [[0]*(capacity+1) for _ in range(itemCount+1)] # 填充DP数组 for i in range(1, itemCount+1): current_weight = weights[i-1] current_value = values[i-1] for j in range(1, capacity+1): if current_weight <= j: # 选或不选当前物品,取价值最大的情况 dp[i][j] = max(dp[i-1][j], dp[i-1][j - current_weight] + current_value) else: # 物品重量超过当前容量,只能不选 dp[i][j] = dp[i-1][j] # 回溯生成taken数组(正确判断哪些物品被选中) taken = [0]*itemCount remaining_capacity = capacity # 从最后一个物品倒推 for i in range(itemCount, 0, -1): # 如果选当前物品后价值变化,说明该物品被选中 if dp[i][remaining_capacity] != dp[i-1][remaining_capacity]: taken[i-1] = 1 # 剩余容量减去当前物品重量,保证后续判断的合法性 remaining_capacity -= weights[i-1] result = dp[itemCount][capacity]
关键修正点
- 调整DP数组维度为
[物品数+1][容量+1],避免索引越界,同时契合0-1背包的标准状态定义。 - 采用倒推回溯的方式生成taken数组:从最后一个物品开始,对比选与不选该物品的价值差异,同时实时更新剩余容量,确保选中的物品总重量不会超过背包上限。
- 循环从1开始遍历物品,对应实际物品索引
i-1,解决了初始循环的越界问题。
内容的提问来源于stack exchange,提问作者whiteSilence11
相关产品推荐
相关产品推荐

