填充两个背包的最佳方法是什么?

17

对于一个背包,动态规划算法可以有效地实现最优填充。但是是否有已知的高效算法可以最优地填充两个背包(容量可以不同)?

我尝试了以下两种方法,但都不正确。

  1. 使用原始DP算法填充一个背包,然后再填充另一个背包。
  2. 首先填充大小为“W1 + W2”的背包,然后将解决方案分成两个解决方案(其中W1和W2是两个背包的容量)。

问题陈述(也可以在维基百科上查看背包问题):

  1. 我们必须用一组物品(每个物品具有重量和价值)填满背包,以便在总重量小于或等于背包大小的情况下最大化从物品中获得的价值。

  2. 我们不能多次使用一个物品。

  3. 我们不能使用部分物品。我们不能取物品的一部分。(每个物品必须完全包括或不包括)。

“我已经尝试过”实际上意味着“在[算法:设计与分析,第2部分](https://lagunita.stanford.edu/courses/course-v1:Engineering+Algorithms2+SelfPaced/about)课程中有人问了我这个问题”。当人们只关注自己时,真是让人爱不释手。 - Abhijit Sarkar
3个回答

12

我将假设这 n 个物品每个只能使用一次,你必须最大化你的利润。

原始的背包问题为 dp[i] = 在重量为 i 时可以获得的最大利润

for i = 1 to n do
  for w = maxW down to a[i].weight do
    if dp[w] < dp[w - a[i].weight] + a[i].gain
      dp[w] = dp[w - a[i].weight] + a[i].gain

现在,我们有两个背包,可以使用 dp[i, j] = 在背包1中放入重量为 i,背包2中放入重量为 j 时可以获得的最佳收益

for i = 1 to n do
  for w1 = maxW1 down to a[i].weight do
    for w2 = maxW2 down to a[i].weight do
      dp[w1, w2] = max
                   {
                       dp[w1, w2], <- we already have the best choice for this pair
                       dp[w1 - a[i].weight, w2] + a[i].gain <- put in knapsack 1
                       dp[w1, w2 - a[i].weight] + a[i].gain <- put in knapsack 2
                   }

时间复杂度为O(n * maxW1 * maxW2),其中maxW是背包可以承载的最大重量。请注意,如果容量很大,则效率不高。


我想到了相同的递归,但是我认为我们在一个特殊情况下有问题。假设'dp [w1-a [i] .weight,w2] + a [i] .gain'和'dp [w1,w2-a [i] .weight] + a [i] .gain'相等。那么你会如何打破平局?这对解决方案产生了影响,因为如果我们有重量为2、5、4和价值为2、5、4的物品以及两个重量为5和6的背包。然后应用此算法,我们将不得不选择将重量为2的物品放入第一个背包还是第二个背包。这个决定自然会对我们正确的最优解产生影响。 - Nikunj Banka
@NikunjBanka - 我觉得这不是问题。你将把重量为2的物品放在第一个背包中的dp [2,0]和第二个背包中的dp [0,2] - 因此你将保留两种可能性。我建议你尝试实现算法并查看其行为。如果因某种原因无法做到,请告诉我,我会提供一个实现。 - IVlad
@IVlad,我不明白你的方程是如何工作的。如果dp[w1,w2]调用了dp[w1,w2],那么dp[w1,w2]的槽位初始化为什么? 另外,我想问一下,物品列表(你答案中的数组a)是否已排序? - aviadch
1
我刚在另一个线程中发现了这个算法。除非两个袋子都有空间,否则它不考虑物品。难道你不需要考虑只有w1或w2之一大于或等于重量的情况吗? - Joe Z

1
原始的DP算法假定您在dp数组中标记可以在背包中获得的值,并通过相应地考虑元素来进行更新。
如果有两个背包,则可以使用二维动态数组,因此当您可以将重量i放入第一个背包和重量j放入第二个背包时,dp [i] [j] = 1。更新与原始DP情况类似。

1
这对于超过2个背包是否可行?n个背包呢? - Essej

1

递归公式如下:

给定n个物品,其中第i个物品的重量为wi,价值为pi。两个背包的容量分别为W1和W2。

对于每个0<=i<=n,0<=a<=W1,0<=b<=W2,定义M[i,a,b]为最大价值。

当a<0或b<0时,M[i,a,b]=-∞;当i=0或a,b=0时,M[i,a,b]=0。

公式如下:

M[i,a,b] = max{M[i-1,a,b], M[i-1,a-wi,b]+pi, M[i-1,a,b-wi]+pi}

问题的每个解都将第i个物品放入背包1、背包2或两个背包都不放。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接