SWE · Coding

0/1背包:每项最多一次,逆序容量防重复

容量受限选最大价值,和完全背包的状态更新方向不同。

题目重点:容量受限选最大价值,和完全背包的状态更新方向不同。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 具体物品表未给,训练items=(正整数weight,value)、非负整数capacity,允许空选。
  • 每项最多一次,不要求恰好填满;负价值可跳过。

解题路线

  1. best[c]为已处理物品且重量≤c的最大价值。处理(weight,value)时best[c]=max(best[c],best[c−weight]+value)。
  2. 容量必须从大到小:读到的best[c−weight]仍是本物品加入之前的状态,因此不会再使用当前项。正序会把同项多次使用,变成完全背包。
  3. 如果返回物品ID,可存二维决策或不可变前驱;直接在一维DP存可变指针可能后来被覆盖导致回溯重复项。

手动走一遍

一项(2,3),容量4,0/1最优3不是6。容量0或全部负价值返回0;如果要求恰好装满需要−∞标不可达。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def maximize(items,capacity):
    if capacity<0 or any(w<=0 for w,v in items):raise ValueError("positive weights, nonnegative capacity")
    best=[0]*(capacity+1)
    for weight,value in items:
        for room in range(capacity,weight-1,-1):best[room]=max(best[room],best[room-weight]+value)
    return best[capacity]

复杂度

n物品W容量O(nW)时间/O(W)空间,是依数值W的伪多项式;不能按W二进制位长度称多项式。

易错点与追问

容易失分的边界

  • weight0正值在此合同拒绝。
  • 输入容量很大时O(W)内存不可承诺,需收益维度或稀疏Pareto讨论。

继续深挖

  • 固定物品数量要求如何增加状态维度?
  • 容量极大、物品很少时meet-in-middle有什么取舍?
✓已复制微信号!