19

In every single example I've found for a 1/0 Knapsack problem using dynamic programming where the items have weights(costs) and profits, it never explicitly says to sort the items list, but in all the examples they are sorted by increasing both weight and profit (higher weights have higher profits in the examples). So my question is when adding items in the matrix from the item array/list, can I add them in any order, or do I add the one with the smallest weight or profit? Because from multiple examples I found I'm not sure if its just a coincidence or you do in fact need to put the smallest weight/profit into the matrix each time

Tommy K
  • 1,759
  • 3
  • 28
  • 51
  • 4
    No, there is no requirement to sort inputs for a Knapsack problem. If it is done, it is being done only to illustrate the solution. You can try running it after inputting in any order and the result should be the same. – Ram Narasimhan Apr 24 '15 at 18:26

6 Answers6

10

The dynamic programming solution is nothing but choosing all the possibilities (using brute force) in an efficient way (just by saving the values for future reference).

Note: We consider all the subsets. Even if the list is sorted or not the total number of subsets will be the same. So in the end all the subsets will get considered.

Shubham Sharma
  • 799
  • 7
  • 31
8

No, you don't need to sort the weights because every row gives the maximum possible value under the weight limit of that row. The maximum will come in the last column of that row.

Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
Shruti Gupta
  • 101
  • 1
  • 3
1

Maybe you are looking at bottom-up Dynamic solutions. And there is one characteristic in Dynamic solution when you solve using the bottom-up method.

The second approach is the bottom-up method. This approach typically depends on some natural notion of the “size” of a subproblem, such that solving any particular subproblem depends only on solving “smaller” subproblems. We sort the subproblems by size and solve them in size order, smallest first. When solving a particular subproblem, we have already solved all of the smaller subproblems its solution depends upon, and we have saved their solutions. We solve each subproblem only once, and when we first see it, we have already solved all of its prerequisite subproblems.

From: Introduction to Algorithm, CORMEN (3rd edition)

Django
  • 103
  • 10
0

The "smaller problem" in this case is just smaller in terms of the number of available items to choose, not about the profits or weights of these items. If given a 3 item list, the sub-problems will be 2 items, and 1 item to choose from.

The smallest problem is first hardcoded (base case), then at each stage of moving from a smaller to bigger problem, the best profit is enumerated, and the max is chosen. At the end, all 2^n combinations would have been considered and the various stages of repeated max will bubble up the largest solution.

Changing the input order, or putting dominated items into the input (like higher weight and lower profit) may just change which argument of max() won at each stage, but the final max result will come from the same selection of items, albeit being selected at different stages in the algorithm for different sort orders or input characteristics.

Han Qi
  • 137
  • 2
  • 7
0

The answer could be found by some random shuffle experiments. which I found is: better in ascending order. correct me if i'm wrong.

gist: https://gist.github.com/whille/39cf7bf8cf5dcf6ac933063735ae54de

Problem described in "Algorithm Design", ISBN: 9780321295354, chapter 6.4. Two methods could be used:

  1. as the chapter used, a M cache to pre-calculated, in which not sub answer is needed.
  2. recursive function, which is simple to understand and test. I found functools.cache of python3.5+ could be use to check how many sub caculation is need, as my gist show: ascending order of test_random() is the smallest in currsize, So it's most efficient, and could extend to float value.

results for 10 random weights(1~100) and 200 knapack:

[(13.527716157276256, 18.371888775465692), (16.18632175987168, 206.88043031085252), (20.14117982372607, 81.52793937986635), (33.28606671929836, 298.8676699147799), (49.12968642850187, 22.037638580809592), (55.279973594800225, 377.3715225559507), (56.56103181962746, 460.9161412820592), (60.38456825749498, 10.721915577913244), (67.98836121062645, 63.47478755362385), (86.49436333909377, 208.06767811169286)]: reverse: False CacheInfo(hits=0, misses=832, maxsize=None, currsize=832) [(86.49436333909377, 208.06767811169286), (67.98836121062645, 63.47478755362385), (60.38456825749498, 10.721915577913244), (56.56103181962746, 460.9161412820592), (55.279973594800225, 377.3715225559507), (49.12968642850187, 22.037638580809592), (33.28606671929836, 298.8676699147799), (20.14117982372607, 81.52793937986635), (16.18632175987168, 206.88043031085252), (13.527716157276256, 18.371888775465692)]: reverse: True CacheInfo(hits=0, misses=1120, maxsize=None, currsize=1120)

Note for method2:

  1. if capacity is much larger, all random orders have equal currsize.
  2. callstack overflow should be avoided for large N, so recurse method should be transformed. Generally a two step method could be used, first map subproblem dependency, and calc. I'ill try later in gist.
whi
  • 2,685
  • 6
  • 33
  • 40
0

I guess, sorting might be required in certain types of knapsack problem. For example consider the problem "Maximum Earnings From Taxi". Here, the input has to be sorted by the starting point of the riders, else we won't get the optimal result.

For example, consider the below input for the above problem:- 9 [[2,3,1],[2,9,2], [3,6,7],[2,3,6]]

If you apply a typical knapsack implementation in recursive approach, without sorting the input we won't get the optimal solution.

Hemanth
  • 5,035
  • 9
  • 41
  • 59