17

The dynamic programming algorithm to optimally fill a knapsack works well in the case of one knapsack. But is there an efficient known algorithm that will optimally fill 2 knapsacks (capacities can be unequal)?

I have tried the following two approaches and neither of them is correct.

  1. First fill the first knapsack using the original DP algorithm to fill one knapsack and then fill the other knapsack.
  2. First fill a knapsack of size W1 + W2 and then split the solution into two solutions (where W1 and W2 are the capacities of the two knapsacks).

Problem statement (see also Knapsack Problem at Wikipedia):

  1. We have to fill the knapsack with a set of items (each item has a weight and a value) so as to maximize the value that we can get from the items while having a total weight less than or equal to the knapsack size.

  2. We cannot use an item multiple times.

  3. We cannot use a part of an item. We cannot take a fraction of an item. (Every item must be either fully included or not).
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Nikunj Banka
  • 11,117
  • 16
  • 74
  • 112
  • By "I have tried", what he really means is that "I was asked this question in the [Algorithms: Design and Analysis, Part 2](https://lagunita.stanford.edu/courses/course-v1:Engineering+Algorithms2+SelfPaced/about) class". Gotta love it when people make it only about themselves. – Abhijit Sarkar Dec 25 '18 at 03:50

3 Answers3

12

I will assume each of the n items can only be used once, and you must maximize your profit.

Original knapsack is dp[i] = best profit you can obtain for weight 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

Now, since we have two knapsacks, we can use dp[i, j] = best profit you can obtain for weight i in knapsack 1 and j in knapsack 2

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
                   }

Time complexity is O(n * maxW1 * maxW2), where maxW is the maximum weight the knapsack can carry. Note that this isn't very efficient if the capacities are large.

IVlad
  • 43,099
  • 13
  • 111
  • 179
  • I thought of the same recurrence but I think we have a problem here in a special case. Suppose 'dp[w1 - a[i].weight, w2] + a[i].gain' and 'dp[w1, w2 - a[i].weight] + a[i].gain' are equal . Then how will you break ties ? This has consequences on the solution as if we have items of weights 2,5,4 and values 2,5,4 respectively and two knapsacks of weights 5 and 6 . Then applying this algorithm, we will have to choose whether to put the item with weight 2 in the first knapsack or the second . This decision will naturally have consequences on our correct optimal solution. – Nikunj Banka Feb 10 '13 at 03:02
  • @NikunjBanka - I don't think that's a problem. You will put the item with weight two in the first knapsack on `dp[2, 0]` and in the second knapsack on `dp[0, 2]` - so you will keep both possibilities. I suggest you try to implement the algorithm and see how it behaves. If you can't for some reason, let me know and I'll provide an implementation. – IVlad Feb 10 '13 at 11:54
  • @IVlad, didn't understand how your equation work. if dp[w1,w2] call to dp[w1,w2] .what was the slot dp[w1,w2] initialize to? also i want to ask if the list of items (array a in your answer) is sorted – aviadch Nov 26 '13 at 08:51
  • 1
    I just came across this algorithm from another thread. It fails to consider objects unless both sacks have room. You need to also consider cases where only one of w1 or w2 is greater-or-equal-to weight, don't you? – Joe Z Nov 28 '13 at 01:39
1

The original DP assumes you mark in the dp array that values which you can obtain in the knapsack, and updates are done by consequently considering the elements.
In case of 2 knapsacks you can use 2-dimensional dynamic array, so dp[ i ][ j ] = 1 when you can put weight i to first and weight j to second knapsack. Update is similar to original DP case.

Grigor Gevorgyan
  • 6,753
  • 4
  • 35
  • 64
1

The recursive formula is anybody is looking:

Given n items, such that item i has weight wi and value pi. The two knapsacks havk capacities of W1 and W2.

For every 0<=i<=n, 0<=a<=W1, 0<=b<=W2, denote M[i,a,b] the maximal value.

for a<0 or b<0 - M[i,a,b] = −∞ for i=0, or a,b=0 - M[i,a,b] = 0

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

Every solution to the problem with i items either has item i in knapsack 1, in knapsack 2, or in none of them.

sheldonzy
  • 5,505
  • 9
  • 48
  • 86