0-1 背包再访

Posted

技术标签:

【中文标题】0-1 背包再访【英文标题】:0-1 Knapsack revisited 【发布时间】:2012-06-07 08:42:14 【问题描述】:

嗯,这是一个古老的 0-1 背包问题,但在找到我能得到的最高总价格后,我需要找到我可以携带的物品。但是对于下面的测试用例(共3项)

10 (max weight that I can carry)
5 3 (weight and value for each item)
5 2
6 5

这里的最高价格是 5。但重量可以是 610(5+5) 。两者都会给出相同的价格,但显然可行的是 6 公斤的物品而不是 10 公斤的物品。我想提示我如何从 dp 矩阵计算这个。我得到了这个测试用例的以下矩阵。

0 0 0 0 3 3 3 3 3 3 
0 0 0 0 3 3 3 3 3 5 
0 0 0 0 3 5 5 5 5 5 

使用此算法,它发现重量为 10,但最佳重量为 6 公斤。

i=n, k=W(max weight)// n= total items

while i,k > 0

if dp[i,k] ≠ dp[i−1,k] then 
mark the ith item as in the knapsack
i = i−1, k = k-w(weight of ith item)

else
i = i−1

【问题讨论】:

【参考方案1】:

简单的解决方案是在不同尺寸的袋子上反复运行背包算法,并选择最小的袋子,但仍能提供与原始袋子相同的价值。

这可以在重量 [0,W] 上使用 binary search 来完成 - 因此您将运行背包算法总计 O(logW) 次,从而为您提供总计 O(nW*log(W)) 解决方案,以找到最大值和可能的最小袋子尺寸。

如何暗示二分搜索的想法: 让原始包的大小为W,运行knapsack(W,items),得到value。现在检查knapsack(W/2,items) 是否仍然返回value。如果是 - 在(0,W/2] 范围内搜索。如果没有,请在(W/2,W] 范围内搜索,直到找到返回value 的最小包大小。

【讨论】:

你能解释一下我们可以在权重上应用二分搜索的场景吗 @Imposter:让原始包的大小为W,运行knapsack(W,items),得到value。现在检查knapsack(W/2,items) 是否仍然返回值。如果是 - 在范围 (0,W/2] 中搜索。如果不是,则在范围 (W/2,W] 中搜索,直到找到返回 value 的最小袋子大小。清楚吗?如果是的 - 我会将其添加到答案中。 后面的问题看不懂 在剪枝概念中,我们消除了无法产生优化解决方案的额外计算。所以我们以同样的方式运行 knapsack(W,items) 并获取值。现在检查 knapsack(W/2,items) 是否仍然返回值。如果是 - 在范围 (0,W/2] 中搜索。如果不是,则在范围 (W/2,W] 中搜索,直到找到返回值的最小袋子大小。在上述过程中,我们正在消除两半中的任何一个..我希望我很清楚 @Imposter:确切地说,每次迭代都会削减范围的一半,因此要获得包含单个元素的范围 - 您需要 O(logW) 迭代,每次花费 O(nW)(因为每次迭代都会调用背包算法)

以上是关于0-1 背包再访的主要内容,如果未能解决你的问题,请参考以下文章

背包0-1背包与完全背包一维数组实现

0-1背包问题的回溯法代码

背包问题(0-1背包+完全背包)

背包问题之0-1背包

0-1背包问题 —— 四种解法解题

C++ 算法主题系列之集结0-1背包问题的所有求解方案