Knapsack

Choose the most valuable combination of items without going over a weight or budget limit.

Complexity
NP-hard
Used for
Budget allocation, Cargo loading, Investment selection
In this lab
Dynamic programming, branch and bound, integer programming, greedy by density
Mode
Algorithm
View
  • Best value for that capacity (brighter is higher)
  • Cell being decided
capacity 0123456789101112131415No itemsβ›Ί Tentweight 6, value 30πŸ”¦ Lanternweight 2, value 9🍳 Stoveweight 4, value 16πŸ’§ Water filterweight 1, value 7πŸ“· Cameraweight 3, value 10πŸ§₯ Jacketweight 4, value 15🎸 Guitarweight 5, value 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  • Tent 6 kg, value 30
  • Lantern 2 kg, value 9
  • Stove 4 kg, value 16
  • Water filter 1 kg, value 7
  • Camera 3 kg, value 10
  • Jacket 4 kg, value 15
  • Guitar 5 kg, value 12
Knapsack: 0 of 15 kg Value 0
1 / 104 Space play ← β†’ step

Exact versus greedy on these items

Total value packed by each approach. Greedy rules are fast but can miss; dynamic programming and branch and bound always find the best.

0 20 40 60 Dynamic programming 68 Branch and bound 68 Greedy by value per kg 62 Greedy by value 68 Greedy by lightest 57

This example in numbers

Camping trip: 7 items, capacity 15 kg.

Best value
68
Weight used
15of 15 kg
Table cells
128
Possible subsets
128

The problem

You have a bag that holds at most W kilograms and a pile of items, each with a weight and a value. Which items should go in so the total value is as high as possible without the bag going over its limit? Every item is all or nothing: you can't pack half a tent.

Swap kilograms for dollars and it becomes budget allocation: projects with costs and expected returns, a fixed budget. Swap them for cubic metres and it's cargo loading. Investment selection, ad-slot planning, choosing which features fit in a release: whenever you pick a subset under one capacity limit, it's a knapsack in disguise. It also turns up inside bigger solvers, for example in column generation for cutting-stock problems.

Formal model

Give each item i a decision variable xi, which is 1 if the item is packed and 0 if not. The 0-1 knapsack problem is then:

maximizeΞ£i vi xi
subject toΞ£i wi xi ≀ W
xi ∈ {0, 1} for every item i

That's an integer linear program with a single constraint. Drop the requirement that xi be 0 or 1 and allow fractions, and the problem becomes easy: greedy by value per kilogram is then exactly optimal. The whole difficulty lives in that little ∈ {0, 1}.

Why it's hard

With n items there are 2n possible selections. 30 items give over a billion; 60 items give more than a billion billion. Checking them all is hopeless, and no known algorithm avoids exponential time in the worst case: the decision version ("can we reach value V?") is NP-complete, one of Richard Karp's 21 classic NP-complete problems from 1972.

Nothing: 0 kg, value 0Tent: 6 kg, value 30Lantern: 2 kg, value 9Tent, Lantern: 8 kg, value 39Stove: 4 kg, value 16Tent, Stove: 10 kg, value 46Lantern, Stove: 6 kg, value 25Tent, Lantern, Stove: 12 kg, value 55Water filter: 1 kg, value 7Tent, Water filter: 7 kg, value 37Lantern, Water filter: 3 kg, value 16Tent, Lantern, Water filter: 9 kg, value 46Stove, Water filter: 5 kg, value 23Tent, Stove, Water filter: 11 kg, value 53Lantern, Stove, Water filter: 7 kg, value 32Tent, Lantern, Stove, Water filter: 13 kg, value 62Camera: 3 kg, value 10Tent, Camera: 9 kg, value 40Lantern, Camera: 5 kg, value 19Tent, Lantern, Camera: 11 kg, value 49Stove, Camera: 7 kg, value 26Tent, Stove, Camera: 13 kg, value 56Lantern, Stove, Camera: 9 kg, value 35Tent, Lantern, Stove, Camera: 15 kg, value 65Water filter, Camera: 4 kg, value 17Tent, Water filter, Camera: 10 kg, value 47Lantern, Water filter, Camera: 6 kg, value 26Tent, Lantern, Water filter, Camera: 12 kg, value 56Stove, Water filter, Camera: 8 kg, value 33Tent, Stove, Water filter, Camera: 14 kg, value 63Lantern, Stove, Water filter, Camera: 10 kg, value 42Tent, Lantern, Stove, Water filter, Camera: 16 kg, value 72 (too heavy)Jacket: 4 kg, value 15Tent, Jacket: 10 kg, value 45Lantern, Jacket: 6 kg, value 24Tent, Lantern, Jacket: 12 kg, value 54Stove, Jacket: 8 kg, value 31Tent, Stove, Jacket: 14 kg, value 61Lantern, Stove, Jacket: 10 kg, value 40Tent, Lantern, Stove, Jacket: 16 kg, value 70 (too heavy)Water filter, Jacket: 5 kg, value 22Tent, Water filter, Jacket: 11 kg, value 52Lantern, Water filter, Jacket: 7 kg, value 31Tent, Lantern, Water filter, Jacket: 13 kg, value 61Stove, Water filter, Jacket: 9 kg, value 38Tent, Stove, Water filter, Jacket: 15 kg, value 68Lantern, Stove, Water filter, Jacket: 11 kg, value 47Tent, Lantern, Stove, Water filter, Jacket: 17 kg, value 77 (too heavy)Camera, Jacket: 7 kg, value 25Tent, Camera, Jacket: 13 kg, value 55Lantern, Camera, Jacket: 9 kg, value 34Tent, Lantern, Camera, Jacket: 15 kg, value 64Stove, Camera, Jacket: 11 kg, value 41Tent, Stove, Camera, Jacket: 17 kg, value 71 (too heavy)Lantern, Stove, Camera, Jacket: 13 kg, value 50Tent, Lantern, Stove, Camera, Jacket: 19 kg, value 80 (too heavy)Water filter, Camera, Jacket: 8 kg, value 32Tent, Water filter, Camera, Jacket: 14 kg, value 62Lantern, Water filter, Camera, Jacket: 10 kg, value 41Tent, Lantern, Water filter, Camera, Jacket: 16 kg, value 71 (too heavy)Stove, Water filter, Camera, Jacket: 12 kg, value 48Tent, Stove, Water filter, Camera, Jacket: 18 kg, value 78 (too heavy)Lantern, Stove, Water filter, Camera, Jacket: 14 kg, value 57Tent, Lantern, Stove, Water filter, Camera, Jacket: 20 kg, value 87 (too heavy)Guitar: 5 kg, value 12Tent, Guitar: 11 kg, value 42Lantern, Guitar: 7 kg, value 21Tent, Lantern, Guitar: 13 kg, value 51Stove, Guitar: 9 kg, value 28Tent, Stove, Guitar: 15 kg, value 58Lantern, Stove, Guitar: 11 kg, value 37Tent, Lantern, Stove, Guitar: 17 kg, value 67 (too heavy)Water filter, Guitar: 6 kg, value 19Tent, Water filter, Guitar: 12 kg, value 49Lantern, Water filter, Guitar: 8 kg, value 28Tent, Lantern, Water filter, Guitar: 14 kg, value 58Stove, Water filter, Guitar: 10 kg, value 35Tent, Stove, Water filter, Guitar: 16 kg, value 65 (too heavy)Lantern, Stove, Water filter, Guitar: 12 kg, value 44Tent, Lantern, Stove, Water filter, Guitar: 18 kg, value 74 (too heavy)Camera, Guitar: 8 kg, value 22Tent, Camera, Guitar: 14 kg, value 52Lantern, Camera, Guitar: 10 kg, value 31Tent, Lantern, Camera, Guitar: 16 kg, value 61 (too heavy)Stove, Camera, Guitar: 12 kg, value 38Tent, Stove, Camera, Guitar: 18 kg, value 68 (too heavy)Lantern, Stove, Camera, Guitar: 14 kg, value 47Tent, Lantern, Stove, Camera, Guitar: 20 kg, value 77 (too heavy)Water filter, Camera, Guitar: 9 kg, value 29Tent, Water filter, Camera, Guitar: 15 kg, value 59Lantern, Water filter, Camera, Guitar: 11 kg, value 38Tent, Lantern, Water filter, Camera, Guitar: 17 kg, value 68 (too heavy)Stove, Water filter, Camera, Guitar: 13 kg, value 45Tent, Stove, Water filter, Camera, Guitar: 19 kg, value 75 (too heavy)Lantern, Stove, Water filter, Camera, Guitar: 15 kg, value 54Tent, Lantern, Stove, Water filter, Camera, Guitar: 21 kg, value 84 (too heavy)Jacket, Guitar: 9 kg, value 27Tent, Jacket, Guitar: 15 kg, value 57Lantern, Jacket, Guitar: 11 kg, value 36Tent, Lantern, Jacket, Guitar: 17 kg, value 66 (too heavy)Stove, Jacket, Guitar: 13 kg, value 43Tent, Stove, Jacket, Guitar: 19 kg, value 73 (too heavy)Lantern, Stove, Jacket, Guitar: 15 kg, value 52Tent, Lantern, Stove, Jacket, Guitar: 21 kg, value 82 (too heavy)Water filter, Jacket, Guitar: 10 kg, value 34Tent, Water filter, Jacket, Guitar: 16 kg, value 64 (too heavy)Lantern, Water filter, Jacket, Guitar: 12 kg, value 43Tent, Lantern, Water filter, Jacket, Guitar: 18 kg, value 73 (too heavy)Stove, Water filter, Jacket, Guitar: 14 kg, value 50Tent, Stove, Water filter, Jacket, Guitar: 20 kg, value 80 (too heavy)Lantern, Stove, Water filter, Jacket, Guitar: 16 kg, value 59 (too heavy)Tent, Lantern, Stove, Water filter, Jacket, Guitar: 22 kg, value 89 (too heavy)Camera, Jacket, Guitar: 12 kg, value 37Tent, Camera, Jacket, Guitar: 18 kg, value 67 (too heavy)Lantern, Camera, Jacket, Guitar: 14 kg, value 46Tent, Lantern, Camera, Jacket, Guitar: 20 kg, value 76 (too heavy)Stove, Camera, Jacket, Guitar: 16 kg, value 53 (too heavy)Tent, Stove, Camera, Jacket, Guitar: 22 kg, value 83 (too heavy)Lantern, Stove, Camera, Jacket, Guitar: 18 kg, value 62 (too heavy)Tent, Lantern, Stove, Camera, Jacket, Guitar: 24 kg, value 92 (too heavy)Water filter, Camera, Jacket, Guitar: 13 kg, value 44Tent, Water filter, Camera, Jacket, Guitar: 19 kg, value 74 (too heavy)Lantern, Water filter, Camera, Jacket, Guitar: 15 kg, value 53Tent, Lantern, Water filter, Camera, Jacket, Guitar: 21 kg, value 83 (too heavy)Stove, Water filter, Camera, Jacket, Guitar: 17 kg, value 60 (too heavy)Tent, Stove, Water filter, Camera, Jacket, Guitar: 23 kg, value 90 (too heavy)Lantern, Stove, Water filter, Camera, Jacket, Guitar: 19 kg, value 69 (too heavy)Tent, Lantern, Stove, Water filter, Camera, Jacket, Guitar: 25 kg, value 99 (too heavy)
Every square is one way to choose items from the current example: all 128 of them (27). Dark squares are too heavy. The rest get lighter as their value rises, and the amber square is the best. Only 91 fit at all. Hover a square to see which items it holds. Brute force has to check every square; dynamic programming never looks at them individually.

And yet the dynamic program in this lab solves real instances quickly. The catch is in its running time, O(nΒ·W): it depends on the value of the capacity, not on the number of digits needed to write it down. Add one digit to W and the table gets ten times wider. Algorithms like this are called pseudo-polynomial: fast when the numbers are small, exponential in the size of the input when they're huge. That's why knapsack is called "weakly" NP-hard.

Data structures

The DP table

The core of the exact method is a two-dimensional array dp[i][w] with n + 1 rows and W + 1 columns. Cell dp[i][w] answers a smaller question: what's the best value using only the first i items with capacity w? Each cell depends on just two cells in the row above, so the table fills row by row in a fixed order, with no recursion and no repeated work.

no fitdp[i][w] = dp[iβˆ’1][w]  when wi > w
otherwisedp[i][w] = max(dp[iβˆ’1][w], vi + dp[iβˆ’1][w βˆ’ wi])

Keeping the whole table costs O(nΒ·W) memory but lets you walk back from the bottom-right cell to recover which items were chosen: whenever a cell differs from the one above it, that row's item was packed. If you only need the best value, one row of length W + 1 is enough: sweep it from right to left for each item, and memory drops to O(W).

A sorted array for greedy

The greedy heuristic needs nothing more than the items sorted by value per kilogram. Sorting dominates its cost at O(n log n); the packing pass afterwards is a single loop.

The algorithms

Dynamic programming (exact)

The key observation is the principle of optimality: in the best packing for capacity w, either item i is left out, and the rest is the best packing of the first i βˆ’ 1 items for w, or it's in, and the rest is the best packing of the first i βˆ’ 1 items for w βˆ’ wi. Compare the two and keep the larger. Step through the lab and watch each cell make exactly that decision.

Branch and bound (exact)

Brute force walks a binary tree: each level decides one item, take it or skip it, and the 2n leaves are all possible packings. Branch and bound walks the same tree but carries two numbers. The best is the value of the best packing found so far. A node's bound is an optimistic estimate of anything below it: fill the remaining room greedily by density and allow one item to be taken fractionally. Because fractions make the problem easier, the bound can never be beaten. When a node's bound is no better than the best, its whole subtree is cut unexplored.

Two choices make the cuts happen early. Items are decided densest first, and "take" is tried before "skip", so a strong packing is found quickly and raises the bar for everything after it. Watch the node count in the lab: on most examples the search visits a small fraction of the full tree, yet the answer is proven optimal, just like dynamic programming. Unlike the DP, its running time doesn't depend on the size of W, which is why solvers prefer it for huge capacities.

As an integer program

The "Integer program" option solves the formal model above the way general-purpose solvers do. It drops the 0-or-1 rule, solves the resulting linear program with the simplex method, and branches on a variable that came out fractional: one child forces it to 1, the other to 0. For knapsack the relaxation is exactly the fractional greedy bound, but the search branches on the item that is split, not simply the next one in line, so it usually needs far fewer nodes than plain branch and bound. On the camping trip it proves the optimum after five linear programs.

Greedy by value density

Rank items by value Γ· weight and pack each one that still fits. It's intuitive and instant, but it can be badly wrong. In the greedy trap example, the statue has the best ratio, so greedy packs it first and then can't fit the painting and the vase, which together are worth more. Greedy can be made safe with one small fix: return the better of the greedy packing and the single most valuable item that fits. That simple variant is never worse than half the optimum.

ApproachTimeGuarantee
Brute forceO(2nΒ·n)Optimal, but only for tiny n
Dynamic programmingO(nΒ·W)Optimal; slow when W is huge
Branch and boundO(2n) worst case, usually far lessOptimal
Greedy by densityO(n log n)None; can be arbitrarily bad
Greedy or best single itemO(n log n)At least Β½ of the optimum
FPTAS (value scaling)O(n3/Ξ΅)At least (1 βˆ’ Ξ΅) of the optimum

Beyond this lab

  • Approximation schemes. Round values down to a coarser scale and run a DP over values instead of weights. You choose the accuracy Ξ΅ and pay for it in time: a fully polynomial-time approximation scheme (FPTAS).
  • Meet in the middle. Split the items in half, list all subsets of each half, sort one list, and match. That's about 2n/2 work instead of 2n, useful when weights are huge but n is around 40.
  • Variants. Unbounded knapsack (unlimited copies of each item), bounded knapsack (up to k copies), multidimensional knapsack (weight and volume limits), multiple knapsacks, and quadratic knapsack, where pairs of items add value together.

A little history

The name is usually credited to the mathematician Tobias Dantzig in the early twentieth century. His son George Dantzig, the inventor of the simplex method, studied the problem in 1957 and gave the greedy ratio rule and the LP-relaxation bound still used in branch and bound today. Dynamic programming came from Richard Bellman in the 1950s. Karp's 1972 paper put knapsack on the first list of NP-complete problems, and in 1975 Ibarra and Kim showed it could be approximated as closely as you like in polynomial time.

The problem even had a turn in cryptography: the Merkle–Hellman cryptosystem of 1978 hid messages in knapsack instances. Adi Shamir broke it in 1982, a reminder that "NP-hard in the worst case" doesn't mean every instance is hard.