Introduction

Three classical DP problems share a tabular fill and a reconstruction step: the 0/1 knapsack problem (and its decision twin subset sum), and matrix-chain multiplication. Density order solves the fractional knapsack but fails for 0/1; matrix-chain parenthesization has no useful greedy rule either (CLRS Exercise 15.3-4). Both need DP.

This note states the recurrences, works a full knapsack table and a small matrix-chain table, and records the standard complexities Θ(nW)\Theta(nW) and Θ(n3)\Theta(n^3).

Prerequisites

Core concepts

0/1 knapsack

Input. nn items with weights wi>0w_i > 0 and values vi≥0v_i \ge 0, capacity WW. Each item is taken wholly or not at all.

State. Let V[i,w]V[i,w] be the maximum value using a subset of the first ii items with total weight at most ww.

V[i,w]={0if i=0 or w=0,V[i−1,w]if wi>w,max⁡(V[i−1,w], vi+V[i−1,w−wi])if wi≤w.V[i,w] = \begin{cases} 0 & \text{if } i = 0 \text{ or } w = 0, \\ V[i-1,w] & \text{if } w_i > w, \\ \max\bigl(V[i-1,w],\, v_i + V[i-1,w-w_i]\bigr) & \text{if } w_i \le w. \end{cases}

Answer V[n,W]V[n,W]. Time and space Θ(nW)\Theta(nW) (pseudo-polynomial in the numeric magnitude of WW).

Subset sum

Decision version. Given positive integers a1,…,ana_1,\ldots,a_n and target TT, does a subset sum to TT? Same table with values replaced by booleans (or by 0/1): item ii with weight aia_i and value aia_i, capacity TT; accept if V[n,T]=TV[n,T] = T. The optimisation version (subset of sum closest to TT without exceeding) is the knapsack table with vi=wi=aiv_i = w_i = a_i.

Matrix-chain multiplication

Input. Dimensions p0,p1,…,pnp_0,p_1,\ldots,p_n for matrices A1,…,AnA_1,\ldots,A_n with AiA_i of size pi−1×pip_{i-1} \times p_i.

Goal. Fully parenthesize the product A1A2⋯AnA_1 A_2 \cdots A_n to minimise the number of scalar multiplications. Multiplying an a×ba\times b matrix by a b×cb\times c matrix costs abcabc.

State. Let m[i,j]m[i,j] be the minimum cost of computing Ai⋯AjA_i \cdots A_j, and let s[i,j]s[i,j] be an optimal split index.

m[i,i]=0,m[i,j]=min⁡i≤k<j(m[i,k]+m[k+1,j]+pi−1pkpj)(i<j).m[i,i] = 0, \qquad m[i,j] = \min_{i \le k < j}\bigl(m[i,k] + m[k+1,j] + p_{i-1} p_k p_j\bigr) \quad (i < j).

Number of states Θ(n2)\Theta(n^2); each state tries O(n)O(n) splits: Θ(n3)\Theta(n^3) time. The number of full parenthesizations is the Catalan number Cn−1=1n(2n−2n−1)C_{n-1} = \frac{1}{n}\binom{2n-2}{n-1}, which is exponential, so enumeration is hopeless.

Algorithms and pseudocode

Pseudocode uses 1-based arrays, <- for assignment and A[i..j] for the subarray from position ii to position jj.

0/1 knapsack

Preconditions: W≥0W\ge0 and all w[i]>0w[i]>0 are integers; ww denotes the weight array, never a loop counter.

Text
ZERO-ONE-KNAPSACK(v, w, W, n)
 1  let V[0..n, 0..W] be a new table
 2  for wt <- 0 to W
 3      V[0, wt] <- 0
 4  for i <- 1 to n
 5      V[i, 0] <- 0
 6      for wt <- 1 to W
 7          V[i, wt] <- V[i - 1, wt]
 8          if w[i] <= wt then
 9              V[i, wt] <- max(V[i, wt], v[i] + V[i - 1, wt - w[i]])
10  return V[n, W]

Reconstruction. From (n,W)(n,W): if V[i,w]=V[i−1,w]V[i,w] = V[i-1,w] then item ii is unused, step to (i−1,w)(i-1,w); otherwise item ii is used, emit ii and step to (i−1,w−wi)(i-1, w-w_i).

Space. Only the previous row is needed for the value: O(W)O(W) extra space. Reconstruction then needs either the full table or a separate choice bit per cell.

One-array version: the direction of the inner loop matters. With a single array d[0..W] updated as d[wt] <- max(d[wt], v[i] + d[wt - w[i]]), scan wt downward from WW to wiw_i for 0/1 knapsack. Then d[wt - w[i]] still holds the value from row i−1i-1, so item ii is used at most once. Scanning upward reads values already updated in row ii and silently solves the unbounded knapsack instead. On the four-item example below, the upward scan gives 20 at capacity 6 (item 3 taken twice) where the 0/1 answer is 17.

Edge cases. W=0W = 0 or n=0n = 0 returns 0. Items with wi>Ww_i > W are never taken. Ties do not affect the optimal value. They do affect which subset is reported: the reconstruction rule above treats item ii as unused whenever V[i,w]=V[i−1,w]V[i,w] = V[i-1,w], so on a tie it prefers to exclude. State the tie-break if a question asks which subset.

Matrix-chain order

Text
MATRIX-CHAIN-ORDER(p)
 1  n <- p.length - 1
 2  let m[1..n, 1..n] and s[1..n, 1..n] be new tables
 3  for i <- 1 to n
 4      m[i, i] <- 0
 5  for ell <- 2 to n                    // chain length
 6      for i <- 1 to n - ell + 1
 7          j <- i + ell - 1
 8          m[i, j] <- infinity
 9          for k <- i to j - 1
10              q <- m[i, k] + m[k + 1, j] + p[i - 1] * p[k] * p[j]
11              if q < m[i, j] then
12                  m[i, j] <- q
13                  s[i, j] <- k
14  return (m, s)

Time / space. Θ(n3)\Theta(n^3) time, Θ(n2)\Theta(n^2) space. Fill by increasing chain length ell so that every shorter chain is already known.

Printing the parenthesization. Recursively: if i=ji = j print AiA_i; else print ( + chain i..s[i,j]i..s[i,j] + chain s[i,j]+1..js[i,j]+1..j + ).

Exact counts. The table has n(n−1)/2n(n-1)/2 non-trivial cells m[i,j]m[i,j] with i<ji < j. Line 10 runs once per pair (i,j)(i,j) and split kk, that is ∑ℓ=2n(n−ℓ+1)(ℓ−1)=(n3−n)/6\sum_{\ell=2}^{n} (n-\ell+1)(\ell-1) = (n^3 - n)/6 times. For n=4n = 4: 6 cells and 10 evaluations of qq.

Cost model. Multiplying a p×qp \times q matrix by a q×rq \times r matrix with the standard method takes pqrpqr scalar multiplications (and pr(q−1)pr(q-1) additions) and yields a p×rp \times r matrix. Matrix-chain questions count multiplications only.

Mathematical explanation

Optimal substructure for knapsack

In any optimal packing of capacity ww using items 1..i1..i, item ii is either absent (then the packing is optimal for i−1,wi-1,w) or present (then the rest is optimal for i−1,w−wii-1, w-w_i). Those are the only two options, so the recurrence is exhaustive.

Why density greedy fails

Items (v,w)=(60,10),(100,20),(120,30)(v,w) = (60,10), (100,20), (120,30), W=50W = 50. Densities 6, 5, 4. Greedy-by-density for 0/1 takes the first two (value 160) and cannot fit the third; the optimum is items 2 and 3 (value 220). The fractional optimum on the same instance is 240 (Greedy Algorithms).

Optimal substructure for matrix-chain

An optimal parenthesization of Ai⋯AjA_i \cdots A_j splits at some kk into Ai⋯AkA_i \cdots A_k and Ak+1⋯AjA_{k+1} \cdots A_j. Each side must itself be optimally parenthesized, otherwise a cheaper side could replace it. Minimising over kk yields m[i,j]m[i,j] (CLRS 3e, Section 15.2).

Catalan bound

The number of ways to parenthesize nn matrices is Cn−1C_{n-1}. For n=4n = 4, C3=5C_3 = 5; for n=10n = 10, C9=4862C_9 = 4862. DP evaluates each of the Θ(n2)\Theta(n^2) subchains once instead of enumerating trees.

Worked examples

0/1 knapsack, four items

Items (v,w)(v,w): (1,1),(6,2),(10,3),(16,5)(1,1), (6,2), (10,3), (16,5); W=7W = 7. Index items 1..4 in that order.

Final row V[4,0..7]V[4,0..7] equals 0,1,6,10,11,16,17,220,1,6,10,11,16,17,22. Optimum 22: items 2 and 4 (weights 2+5=72+5=7, values 6+16=226+16=22), or check by reconstruction from (4,7)(4,7): V[4,7]=16+V[3,2]V[4,7] = 16 + V[3,2] and V[3,2]=6V[3,2] = 6, so items 4 and 2.

Selected cells used in the figure:

i\wi \backslash w01234567
000000000
101111111
201677777
30161011161717
40161011161722
0/1 knapsack DP table for four items and capacity 7
Figure 1. 0/1 knapsack table for items (v,w)=(1,1),(6,2),(10,3),(16,5)(v,w) = (1,1),(6,2),(10,3),(16,5) and W=7W = 7: the bottom-right entry 22 is optimal, attained by taking items 2 and 4.

Matrix-chain on four matrices

Dimensions p=⟨5,4,6,2,7⟩p = \langle 5, 4, 6, 2, 7 \rangle (matrices 5×45\times 4, 4×64\times 6, 6×26\times 2, 2×72\times 7).

Chain length 2:

  • m[1,2]=5⋅4⋅6=120m[1,2] = 5\cdot 4\cdot 6 = 120, s=1s=1
  • m[2,3]=4⋅6⋅2=48m[2,3] = 4\cdot 6\cdot 2 = 48, s=2s=2
  • m[3,4]=6⋅2⋅7=84m[3,4] = 6\cdot 2\cdot 7 = 84, s=3s=3

Chain length 3:

  • m[1,3]=min⁡(0+48+5⋅4⋅2,  120+0+5⋅6⋅2)=min⁡(48+40,120+60)=88m[1,3] = \min(0+48+5\cdot 4\cdot 2,\; 120+0+5\cdot 6\cdot 2) = \min(48+40,120+60) = 88, s=1s=1
  • m[2,4]=min⁡(0+84+4⋅6⋅7,  48+0+4⋅2⋅7)=min⁡(84+168,48+56)=104m[2,4] = \min(0+84+4\cdot 6\cdot 7,\; 48+0+4\cdot 2\cdot 7) = \min(84+168,48+56) = 104, s=3s=3

Chain length 4:

  • m[1,4]=min⁡(0+104+5⋅4⋅7,  120+84+5⋅6⋅7,  88+0+5⋅2⋅7)=min⁡(104+140,  204+210,  88+70)=min⁡(244,414,158)=158m[1,4] = \min(0+104+5\cdot 4\cdot 7,\; 120+84+5\cdot 6\cdot 7,\; 88+0+5\cdot 2\cdot 7) = \min(104+140,\; 204+210,\; 88+70) = \min(244,414,158) = 158, s=3s=3.

Optimal cost 158 with split s[1,4]=3s[1,4] = 3: (A1A2A3) (A4)(A_1 A_2 A_3)\,(A_4). Expanding A1..A3A_1..A_3 with s[1,3]=1s[1,3] = 1 gives ((A1(A2A3))A4)((A_1(A_2 A_3))A_4).

All C3=5C_3 = 5 parenthesizations, for comparison:

ParenthesizationCost
((A1(A2A3))A4)((A_1(A_2 A_3))A_4)158
(A1((A2A3)A4))(A_1((A_2 A_3)A_4))244
(((A1A2)A3)A4)(((A_1 A_2)A_3)A_4)250
(A1(A2(A3A4)))(A_1(A_2(A_3 A_4)))392
((A1A2)(A3A4))((A_1 A_2)(A_3 A_4))414

The worst order costs more than 2.6 times the best. Plain left-to-right evaluation (250) is not optimal here.

Matrix-chain cost table and split table for four matrices
Figure 2. Matrix-chain tables for p=⟨5,4,6,2,7⟩p = \langle 5,4,6,2,7 \rangle: m[1,4]=158m[1,4] = 158 with split s[1,4]=3s[1,4] = 3, yielding the parenthesization ((A1(A2A3))A4)((A_1(A_2 A_3))A_4).

Important properties and observations

  • 0/1 knapsack is pseudo-polynomial: Θ(nW)\Theta(nW) is polynomial in nn and WW, not in the bit length of WW. The decision version is NP-complete, so no algorithm polynomial in the input size is expected unless P = NP.
  • Unbounded knapsack (unlimited copies of each item) changes the transition to max⁡(V[i−1,w], vi+V[i,w−wi])\max(V[i-1,w],\, v_i + V[i, w-w_i]) (same-row reuse). Do not mix the two recurrences. For the four-item example, the unbounded optimum by capacity 0..70..7 is 0,1,6,10,12,16,20,220, 1, 6, 10, 12, 16, 20, 22: capacity 4 gives 12 (item 2 twice) against 11 for 0/1.
  • Increasing chain length is one convenient valid matrix-chain fill order. Ordinary top-to-bottom row-major order is invalid. Another valid order is rows i=n down to 1, with columns j=i+1 up to n: both required subchains are then already computed.
  • The split table s[i,j]s[i,j] stores one optimal kk; several kk may share the same cost.

Common misconceptions.

  • "Knapsack is O(nlg⁡n)O(n \lg n) like fractional." Only the fractional version is greedy.
  • "Matrix-chain needs n!n! parenthesizations." The count is Catalan, still exponential, which is why DP helps.
  • "Subset sum needs values different from weights." Setting vi=wiv_i = w_i reduces knapsack to subset sum.

GATE examination perspective

  • FILL ONE ROW. A question may give a partially filled knapsack table; compute the next cell from the recurrence.
  • PSEUDO-POLYNOMIAL. State Θ(nW)\Theta(nW), not "polynomial" without qualification.
  • CHAIN LENGTH ORDER. Matrix-chain questions ask for m[i,j]m[i,j] or s[i,j]s[i,j] after a few lengths.
  • PARENTHESES COUNT. Cn−1C_{n-1} ways; DP cost Θ(n3)\Theta(n^3).
  • RECONSTRUCTION. Be ready to list which items are taken or to write the parenthesization from ss.
  • ONE-ARRAY LOOP DIRECTION. Downward for 0/1, upward for unbounded; a question may show code and ask which problem it solves.
  • MULTIPLICATION COUNT. pqrpqr per product; compare every parenthesization only when the chain is short (5 orders for 4 matrices, 14 for 5).

Summary

Sources

  1. T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein, Introduction to Algorithms, 3rd ed., MIT Press, 2009: Chapter 15, Section 15.2 (matrix-chain multiplication) and Section 15.3 (elements of dynamic programming); Exercise 15.3-4 (greedy split fails).

Next steps