限制背包解决方案中每个项目的数量

Limiting number of each item in knapsack solution

我试图更好地理解背包问题,并且正在查看此处给出的 "Specific Dynamic Programming solution": http://rosettacode.org/wiki/Knapsack_Problem/Python

我想对其进行修改,以便在解决方案中最多可以使用 items 中的每一项。我认为这可以通过循环遍历重量和体积之外的项目来完成,但这没有用。

感谢任何帮助。

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

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

它选择小于背包重量和体积限制的物品的最大值组合,并允许每个物品多次使用。

我希望它选择重量和价值 < 背包的重量和体积限制的物品的最大值组合,但限制是项目中的每个项目最多只能使用一次。

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

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

如果 W 足够小,该算法非常容易实现并且非常快。

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

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

这样每一项就不能多次计数了。

并且通过首先循环项目,您不会错过项目组合的机会。

例如,当您的 table 为空并且您处理了第一个项目。它将采取当前最好的和最好的位置 [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只用一次

因此,无论 table 值较低的是什么,都不会来自同一项目。

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)

当它完全适合时,return 所有项目。

Running example