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

时间:2015-12-22 00:21:11

标签: algorithm dynamic-programming knapsack-problem

我正在努力更好地理解背包问题,并且正在研究"特定动态编程解决方案"这里给出: http://rosettacode.org/wiki/Knapsack_Problem/Python

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

感谢任何帮助。

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

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

它选择<项的最大值组合。背包的重量和体积限制,允许每个项目多次使用。

我希望它选择具有权重和值的项目的最大值组合<背包的重量和体积限制,但约束条款中的每个项目最多可以使用一次。

2 个答案:

答案 0 :(得分:1)

正如我在评论中提到的,您可以使用O(n * W)动态编程方法,其中n是项目数,W是背包的容量。有关详细信息,请参阅此处:

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

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

答案 1 :(得分:1)

如果您想防止多次使用每件物品:

1)使DP算法减少而不是增加+首先对每个项目进行处理而不是首先在weigth和volume上循环

这样,每个项目不能多次计数多次。

首先循环使用这些项目,你不会错过任何项目组合。

作为一个示例,当您的表为空并处理您的第一个项目时。在[w-weight][v-volume]+value

位置,它将采用当前和最佳的最佳状态
table[w][v] = max(table[w][v], table[w - item.weight][v - item.volume] + item.value)

所以对于 panacea

  • 处理table[25][3]时,当您按递增顺序递增时,3000将为table[50][6]。使它成为6000,使用它2次。

  • 在处理table[25][3]时,按递减顺序0时仍为table[50][6]。使它成为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