【问题标题】:Limiting number of each item in knapsack solution背包解决方案中每个项目的数量限制
【发布时间】:2016-03-28 04:07:58
【问题描述】:

我正在努力更好地理解背包问题,并正在查看此处给出的“特定动态编程解决方案”: http://rosettacode.org/wiki/Knapsack_Problem/Python

我想修改它,以便在解决方案中最多使用 items 中的每个项目。我认为这可以通过遍历重量和体积之外的项目来完成,但这不起作用。

感谢任何帮助。

编辑: 例子: 目前代码定义了一个项目列表

items = [Bounty('panacea', 3000,   3,  25),
         Bounty('ichor',   1800,   2,  15),
         Bounty('gold',    2500,  20,   2)]

它选择物品的最大值组合,即

我希望它选择重量和价值

【问题讨论】:

  • 向我们展示您目前拥有的东西,以及什么不起作用?
  • @SamSegers 我正在使用该链接的“特定动态编程解决方案”下列出的内容。现在它返回“可实现的最大值(通过动态编程)是 54500 灵丹妙药,灵药,黄金项目的数量分别是:[9,0,11]”但是,我希望它只允许在每个项目最多使用 1 个。我计划从一个包含更多项目的列表开始工作,但列表中每个项目只有一个可用单位。
  • 我想你的意思是你想返回最好的项目类型作为输出?添加一个例子供读者理解。
  • @SamSegers 我编辑了原帖。
  • 你可以尝试一个在 O(n * W) 中工作的众所周知的算法,其中 n 是物品的数量,W 是背包的容量。如果您想对此进行详细解答,请告诉我。

标签: algorithm dynamic-programming knapsack-problem


【解决方案1】:

正如我在评论中提到的,您可以使用O(n * W) 动态编程方法,其中n 是项目数,W 是背包的容量。更多详情请参考这里:

https://en.wikipedia.org/wiki/Knapsack_problem#0.2F1_knapsack_problem

只要W足够小,算法就很容易实现,速度也很快。

【讨论】:

  • 我理解并已经实现了这一点。但是,我无法通过多个约束来限制,即 OP 中的链接除了重量之外还涉及体积。
  • 您能否尝试更详细地解释您错过的内容?似乎您想决定是否最好拿一个项目,而上面的算法正是这样做的。一开始你可以扔掉额外的物品,这样每种最多只剩下1件。这有意义吗?
  • 这种方法限制了不同项目的数量,据我了解,@sfenske 可以有任意数量的不同项目,只要每种类型只有 1 个。这是一个不同的问题。
【解决方案2】:

如果你想防止每个项目被多次使用:

1) 使 DP 算法减少而不是增加 + 首先处理每个项目,而不是首先循环重量和体积

这样每个项目不能被多次计算多次。

并且通过首先循环项目,您不会冒险丢失项目组合。

例如,当您的表是空的并且您处理您的第一个项目时。它将充分利用当前和最佳位置[w-weight][v-volume]+value

table[w][v] = max(table[w][v], table[w - item.weight][v - item.volume] + item.value)

所以对于灵丹妙药

  • 当您按递增顺序进行时,table[25][3] 在处理 table[50][6] 时将是 3000。 6000,用了2次。

  • 当您按降序进行时,table[25][3] 在处理 table[50][6] 时仍将是 0。 3000,只用一次。

所以无论是在较低的表值中,它都不会来自同一个项目。

2) 检查所有物品是否适合背包

按照实现的方式,当所有物品都适合背包时,这确实会崩溃。

你可以重写这个或者简单地在方法的开头添加一个检查:

def knapsack_dp(items, sack):
    if(sum(item.weight for item in items) <= sack.weight
        and sum(item.volume for item in items) <= sack.volume):
        return [1] * len(items)

当它完全适合时,退回所有物品。

Running example

【讨论】:

  • 谢谢,for w in reversed(xrange(sack.weight + 1)): for v in reversed(xrange(sack.volume + 1)): 给出了越界错误和倒车和删除+ 1 产生一个空袋。或许您可以进一步解释一下这个想法背后的逻辑?
  • 我希望我的解释能帮助你理解为什么会这样。
  • 我想我遵循你的逻辑,但正如我在评论中所说,使用 reversed 会产生错误。
  • 所有的魔法都发生在表格矩阵中。这实际上是在做实际的 DP。遍历每个项目后尝试调试或打印出表格。
猜你喜欢
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
  • 2021-05-25
  • 2011-07-09
  • 1970-01-01
相关资源
最近更新 更多