我正在努力更好地理解背包问题,并且正在研究"特定动态编程解决方案"这里给出: http://rosettacode.org/wiki/Knapsack_Problem/Python
我想修改它,因此最多可以在解决方案中使用项目中的每个项目。我认为这可以通过循环重量和体积之外的项目来完成,但这不起作用。
感谢任何帮助。
编辑: 例: 目前,代码定义了一个项目列表
items = [Bounty('panacea', 3000, 3, 25),
Bounty('ichor', 1800, 2, 15),
Bounty('gold', 2500, 20, 2)]
它选择<项的最大值组合。背包的重量和体积限制,允许每个项目多次使用。
我希望它选择具有权重和值的项目的最大值组合<背包的重量和体积限制,但约束条款中的每个项目最多可以使用一次。
答案 0 :(得分:1)
正如我在评论中提到的,您可以使用O(n * W)
动态编程方法,其中n
是项目数,W
是背包的容量。有关详细信息,请参阅此处:
https://en.wikipedia.org/wiki/Knapsack_problem#0.2F1_knapsack_problem
如果只有W
足够小,该算法非常容易实现并且非常快。
答案 1 :(得分:1)
如果您想防止多次使用每件物品:
这样,每个项目不能多次计数多次。
首先循环使用这些项目,你不会错过任何项目组合。
作为一个示例,当您的表为空并处理您的第一个项目时。在[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,只使用一次。
因此,无论在较低的表值中,它都不会来自同一个项目。
顺便说一下,当所有物品都适合背包时,这确实会崩溃。
您可以重写此内容,或者只是在方法的开头添加一个检查:
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)
当它完全适合时,返回所有项目。