You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

预算支出最大化动态规划实现非最优问题排查

问题定位

你推导的递推方程完全正确,这个问题是经典的0-1背包问题——你没快速匹配到原型,是因为这个场景下每个项目的“价值”等于自身成本,目标是总价值(总支出)尽可能接近背包容量(总预算),和教材里“重量、价值分离”的常规背包描述有细微差异。
你的实现错误和递推逻辑无关,核心是一维滚动数组的遍历逻辑写错了。

错误原因分析

你设计的一维记忆数组C、从右向左填充的思路本身是0-1背包的标准空间优化方案,但你实现时犯了关键错误:

  • 错误维护了一个全局的剩余预算变量,处理项目时只跟踪“选当前项目”这单一路径的预算变化,完全丢弃了“不选当前项目”的并行状态,本质退化成了“遇到能装就装”的贪心算法,自然无法得到全局最优。
  • 额外的细节错误:你提到数组C大小等于B,对应预算0到B的话数组长度需要是B+1,长度为B时最大索引是B-1,本身就无法存储预算满额B的结果。
正确实现步骤

严格按照递推关系落地一维DP的逻辑即可,核心是两层循环的嵌套顺序和遍历方向:

  • 初始化长度为B+1的数组C,所有元素初始值为0,C[b]表示预算为b时能实现的最大支出
  • 外层循环:逐个遍历所有项目p_i,遍历顺序不影响最终结果
  • 内层循环:从最大预算B开始倒序遍历,直到预算值等于当前项目成本p_i为止,对每个预算档位b执行更新:C[b] = max(C[b], C[b - p_i] + p_i)
    • 倒序遍历的作用是保证更新C[b]时,用到的C[b-p_i]是处理上一个项目时的留存状态,不会出现同一个项目被重复选中的问题
  • 所有项目遍历完成后,C[B]就是所求的最大支出值
测试用例推演

用你给出的B=50、P=[10,20,40]用例走一遍流程就能验证正确性:

初始状态:C是长度51的全0数组,索引0~50对应0到50的预算档位

  1. 处理第一个项目p=10:
    从b=50倒序到10更新,所有b>=10的位置C[b] = max(0, C[b-10]+10) = 10
  2. 处理第二个项目p=20:
    从b=50倒序到20更新,例如b=50时取max(10, C[30]+20=30)得30;b=30时取max(10, C[10]+20=30)得30。处理完成后,b>=30档位值为30,20<=b<30档位值为20,10<=b<20档位值为10
  3. 处理第三个项目p=40:
    从b=50倒序到40更新:b=50时取max(30, C[10]+40=50)得50;b=40时取max(30, C[0]+40=40)得40
    最终C[50] = 50,和最优解一致
实现注意事项
  • 绝对不要用全局变量跟踪单条路径的剩余预算:一维DP数组的核心是同时保存所有可能预算档位下的最优值,覆盖“选/不选当前项目”的所有分支状态
  • 内层循环必须倒序:如果改成正序遍历,会变成允许同一个项目重复选取的完全背包逻辑,不符合项目只能选一次的要求
  • 内层循环不需要遍历到0:当预算小于当前项目成本时,项目无法被选中,对应位置的值不需要更新,遍历到p_i即可减少无效计算

内容的提问来源于stack exchange,提问作者Lightsong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 21:45:44