为什么0/1背包的动态编程?

时间:2017-11-09 08:18:03

标签: algorithm dynamic-programming

我查看了许多资源以及this问题,但我仍然困惑为什么我们需要动态编程来解决0/1背包?

问题是:我有N个项目,每个项目的值为Vi,每个项目的权重为Wi。我们有一个总重量为W的袋子。如何选择项目以获得超过重量限制的最佳总值。

我对动态编程方法感到困惑:为什么不计算每个项目的(值/重量)分数,并选择具有最小分数的项目,其重量小于袋子中的剩余重量?

4 个答案:

答案 0 :(得分:3)

对于基于分数的方法,您可以轻松找到反例。

考虑

W=[3, 3, 5]
V=[4, 4, 7]
Wmax=6

您的方法提供了最佳价值Vopt=7(我们从7/5 > 4/3开始采用最后一项),但是前两项会给我们Vopt=8

答案 1 :(得分:2)

正如其他答案所指出的,你的方法存在边缘情况。

为了更好地解释递归解决方案,也许更好地理解它,我建议你用这个推理来解决它:

对于每个“子包”

  1. 如果我们没有拟合元素,则没有最佳元素
  2. 如果我们只有一个拟合元素,那么最好的选择就是元素
  3. 如果我们有多个拟合元素,我们采用每个元素并计算其“子包”的最佳拟合。最好的选择是最高价值的元素/子包组合。
  4. 此算法有效,因为它跨越拟合元素的所有可能组合,并找到具有最高值的组合。

    相反,直接解决方案不可能是the problem is NP-hard

答案 2 :(得分:1)

看看这个反例:

Weight 7, W/V pairs (3/10),(4/12),(5/21)

答案 3 :(得分:1)

当存在单位比例时,贪婪算法失败。例如,请考虑以下示例:

n = 1 2,P = 4 18,W = 2 18,P / W = 2 1

背包容量= 18

根据贪婪算法,它将考虑第一项,因为它的P / W比率更大,因此总利润将是4(因为它不能在第一项之后插入第二项,因为容量减少到16之后插入第一项)。

但实际答案是18。

因此,有多个极端情况,贪婪无法提供最佳解决方案,这就是我们在0/1背包问题中使用动态编程的原因。