← Exam 2 home

4 · Dynamic programming

DPV Ch 6 + lectures 27–29 + HW4 P6–P7. Two exam problems come from here. Expect either "fill this table" (knapsack, edit distance, LCS, LIS) or "design a DP" for a DPV exercise (6.1–6.11 style). Every table and number on this page was computed by script.

Router

If the question says…Subproblem shapeGo to
one sequence, "longest / best subsequence", "ending at"prefix, ending at jLIS, 6.1, 6.2, 6.3, 6.4
two stringstwo prefixes \((i, j)\)edit distance, LCS (6.11), substring (6.8)
capacity / weight limit W, integer weightscapacity \(w\) (and items \(1..j\) if each item once)knapsack
"order of operations", "parenthesize", "where to cut a segment", palindromeinterval \((i, j)\)chain matrix, 6.7, 6.9
treesubtree of \(u\) (in / out)independent set in a tree
weighted intervalsfirst \(k\) by finish timeweighted interval scheduling
rod / length \(n\), sell pieceslength \(j\)rod cutting, HW4 P6

1 · The recipe

  1. Subproblem in words. "\(T[i]\) = the best ____ using only ____ / ending exactly at ____." This is the creative step.
  2. Recurrence by guessing one choice. Last element? Previous element? Item \(j\) in or out? Where is the last split? Write one case per possible answer and take max/min.
  3. Base cases, and where the final answer sits (\(T[n]\), \(T[n, m]\), \(\max_j T[j]\), …).
  4. Fill order: every entry is computed after the entries it reads.
  5. Cost = #subproblems × work per subproblem. Keep back-pointers (which case won) to rebuild the actual solution.

DP = shortest (or longest) path in a hidden DAG. Nodes = subproblems; edge \(u \to v\) when \(v\)'s recurrence reads \(u\); fill order = a topological order; value of an entry = best path to that node; back-pointers = following prev. If the dependencies form a cycle, there is no valid order and the recipe fails (that is why longest simple path in a general graph is hard but easy in a DAG).

Three components (lecture 27): simple subproblems, subproblem optimality (an optimal solution is built from optimal subsolutions), subproblem overlap (store answers, solve each once). Top-down memoization and bottom-up tables solve the same subproblems in the same big-O time.

How to write a DP answer for full marks.
  1. Define the table in one sentence with index ranges: "For \(0 \le j \le n\), let \(P(j)\) = the minimum total penalty of a trip that ends at hotel \(j\)."
  2. Recurrence with every case, plus one justification sentence: "The last day starts at some hotel \(i < j\); the part before it must itself be optimal (cut and paste)."
  3. Base cases written out (\(P(0) = 0\), \(E(i, 0) = i\), …).
  4. Order + answer: "Fill \(j = 1, \dots, n\); return \(P(n)\)."
  5. Running time and space: "\(n\) subproblems × \(O(n)\) each = \(O(n^2)\) time, \(O(n)\) space."
  6. Recover the solution: "Store the \(i\) that achieves the min in prev(\(j\)); follow prev from \(n\) back to 0."
  7. Short DPV-style pseudocode if the question says "give an algorithm".
Missing the definition in words or the running time is where points usually go.

2 · Longest increasing subsequence

$$L(j) = 1 + \max\{L(i) : i < j,\ a_i < a_j\} \quad(\max \emptyset = 0)$$

\(L(j)\) = length of the longest increasing subsequence ending exactly at \(a_j\). Answer \(\max_j L(j)\). Order \(j = 1..n\). \(n\) subproblems × \(O(n)\) = \(O(n^2)\). "Ending at j" is needed because extending a subsequence needs to know its last element.

j12345678
\(a_j\)52863697
\(L(j)\)11222344
prev––112566

Answer 4. Rebuild from \(j = 7\): 9 ← 6 (j=6) ← 3 (j=5) ← 2 (j=2): 2, 3, 6, 9. (2, 3, 6, 7 also has length 4.) prev = the first \(i\) achieving the max.

3 · Edit distance

$$E(i, j) = \min\{\,E(i-1, j) + 1,\ \ E(i, j-1) + 1,\ \ E(i-1, j-1) + \text{diff}(i, j)\,\}$$

\(E(i, j)\) = edit distance between \(x[1..i]\) and \(y[1..j]\). Cases = last column of the alignment: delete \(x_i\), insert \(y_j\), or match/substitute. diff = 0 if \(x_i = y_j\), else 1. Base \(E(i, 0) = i\), \(E(0, j) = j\). Answer \(E(m, n)\). \(O(mn)\) time. With general costs: insert \(\alpha\), delete \(\beta\), substitute \(\gamma\), base \(E(0,j) = j\alpha\), \(E(i,0) = i\beta\).

SNOWY (rows) → SUNNY (columns):

–SUNNY
–012345
S101234
N211123
O322223
W433333
Y544443

Edit distance 3. One optimal alignment: S–NOWY over SUNN–Y (insert U, substitute O→N, delete W). Any of row-by-row, column-by-column or anti-diagonal fill works: each cell reads up, left, and up-left. Only the distance needed → keep two rows, \(O(\min(m,n))\) space.

Boundary trap (lecture correction): boundary entries are \(j\alpha\) and \(i\beta\), not ∞. Return Opt[n, m].

4 · Longest common subsequence (DPV 6.11)

$$c[i, j] = \begin{cases} c[i-1, j-1] + 1 & \text{if } x_i = y_j \\ \max\{c[i-1, j],\ c[i, j-1]\} & \text{otherwise} \end{cases}$$

\(c[i, j]\) = length of an LCS of \(x[1..i]\) and \(y[1..j]\). Base \(c[i, 0] = c[0, j] = 0\). Fill row by row. Answer \(c[m, n]\). \(\Theta(mn)\) time; \(O(\min(m,n))\) space if only the length is needed.

x = ABCBDAB (rows), y = BDCABA (columns):

–BDCABA
–0000000
A0000111
B0111122
C0112222
B0112233
D0122233
A0122334
B0122344

LCS length 4. Trace back from the corner (diagonal on a match; otherwise move to the larger neighbor, up on ties): BCBA.

Proof idea (cut and paste, lecture). If \(x_i = y_j\), an LCS \(z[1..k]\) ends with that letter, and \(z[1..k-1]\) must be an LCS of the shorter prefixes; a longer one plus \(z_k\) would beat \(z\). If \(x_i \ne y_j\), \(z\) skips \(x_i\) or skips \(y_j\), giving the two max terms.

DPV 6.11 exam answer: exactly the above with \(x = x_1..x_n\), \(y = y_1..y_m\): \((n+1)(m+1)\) entries, \(O(1)\) each, \(O(mn)\).

5 · 0/1 knapsack

$$B[k, w] = \begin{cases} B[k-1, w] & \text{if } w_k > w \\ \max\{B[k-1, w],\ B[k-1, w - w_k] + b_k\} & \text{otherwise} \end{cases}$$

\(B[k, w]\) = max benefit using only items \(1..k\) with total weight \(\le w\). Base \(B[0, w] = 0\). Answer \(B[n, W]\). \(O(nW)\): pseudo-polynomial (polynomial in the value \(W\), exponential in its number of bits).

Lecture example, \(W = 9\): items (w, b) = 1 (4, 20), 2 (2, 3), 3 (2, 6), 4 (6, 25), 5 (2, 80).

afterw=0123456789
k=10000202020202020
k=20033202023232323
k=30066202026262929
k=40066202026263131
k=50080808686100100106106

Answer 106. Which items: \(B[5,9] = 106 \ne B[4,9] = 31\) → take 5, go to \(w = 7\). \(B[4,7] = B[3,7] = 26\) → skip 4. \(B[3,7] = 26 \ne B[2,7] = 23\) → take 3, \(w = 5\). \(B[2,5] = B[1,5]\) → skip 2. \(B[1,5] = 20 \ne 0\) → take 1. Items {1, 3, 5}, weight 8.

1-D array trick. Row \(k\) reads only row \(k - 1\), so keep one array and run \(w\) downward:

for w = 0 to W: B[w] = 0
for k = 1 to n:
    for w = W down to w_k:
        if B[w − w_k] + b_k > B[w]: B[w] = B[w − w_k] + b_k

Downward keeps \(B[w - w_k]\) at its row-\((k-1)\) value, so each item is used at most once. Running \(w\) upward lets item \(k\) be reused: that is exactly knapsack with repetition.

6 · Knapsack with repetition (DPV §6.4)

$$K(w) = \max_{i:\, w_i \le w}\{K(w - w_i) + v_i\},\qquad K(0) = 0$$

Guess the last item added. \(W + 1\) subproblems × \(O(n)\) = \(O(nW)\). No item index needed because any item may be used again.

DPV example, \(W = 10\): item 1 (6, $30), item 2 (3, $14), item 3 (4, $16), item 4 (2, $9).

w012345678910
K(w)0091418233032394448

With repetition: $48 (item 1 + two of item 4). Without repetition (0/1), \(K(w, j) = \max\{K(w, j-1),\ K(w - w_j, j-1) + v_j\}\):

items012345678910
10000003030303030
1–20001414143030304444
1–30001416163030304446
1–40091416233030394446

0/1: $46 (items 1 and 3).

7 · Chain matrix multiplication

$$C(i, j) = \min_{i \le k < j}\{C(i, k) + C(k+1, j) + m_{i-1}\, m_k\, m_j\},\qquad C(i, i) = 0$$

\(A_i\) is \(m_{i-1} \times m_i\). \(C(i, j)\) = cheapest cost of computing \(A_i \cdots A_j\). Guess the last multiplication (split \(k\)). Fill by increasing length \(j - i\). Answer \(C(1, n)\). \(\sim n^2/2\) subproblems × \(O(n)\) = \(O(n^3)\).

DPV: A 50×20, B 20×1, C 1×10, D 10×100, so \(m = (50, 20, 1, 10, 100)\).

C(i, j)j=1 (A)j=2 (B)j=3 (C)j=4 (D)
i=101,000 (k=1)1,500 (k=2)7,000 (k=2)
i=20200 (k=2)3,000 (k=2)
i=301,000 (k=3)
i=40

Optimum 7,000 = \((A \times B) \times (C \times D)\): \(1{,}000 + 1{,}000 + 50 \cdot 1 \cdot 100\). Other orders: \(((AB)C)D\) = 51,500; \((A(BC))D\) = 60,200 (this is what "cheapest adjacent pair first" greedy picks); \(A((BC)D)\) = 120,200; \(A(B(CD))\) = 103,000.

Fill-order trap: rows top to bottom is invalid (C(1,4) reads C(2,4), which is below). Valid: by diagonal (length), or rows bottom to top.

8 · Independent set in a tree

$$\text{in}(u) = w(u) + \sum_{c \text{ child of } u} \text{out}(c), \qquad \text{out}(u) = \sum_{c} \max\{\text{in}(c), \text{out}(c)\}$$

Root the tree. in(u)/out(u) = best weight in u's subtree with u taken / not taken. Leaves: in = w, out = 0. Postorder. Answer \(\max\{\text{in(root)}, \text{out(root)}\}\). \(O(n)\) total. DPV's one-number form: \(I(u) = \max\{1 + \sum_{\text{grandchildren}} I,\ \sum_{\text{children}} I\}\) (unit weights).

r5a6b2c3d1e4f2g3
Root r. Vertex weights shown above each vertex: r 5, a 6, b 2, c 3, d 1, e 4, f 2, g 3.
u (postorder)cdafgebr
in(u)3162342 + 5 = 75 + 4 + 5 = 14
out(u)003 + 1 = 4002 + 3 = 5max(4, 5) = 5max(6,4) + max(7,5) = 13

Answer 14: {r, c, d, f, g} = 5 + 3 + 1 + 2 + 3 (brute force agrees). Greedy "heaviest first" takes a (6), then e (4), and stops at 10.

9 · Weighted interval scheduling

$$\text{OPT}(k) = \max\{\text{OPT}(k-1),\ w_k + \text{OPT}(p(s_k) - 1)\},\qquad \text{OPT}(0) = 0$$

Sort by finish time. \(p(s_k)\) = index of the first interval finishing after \(s_k\) starts, so intervals \(1..p(s_k)-1\) are exactly those compatible with \(\ell_k\) that come before it. Either skip \(\ell_k\) or take it. Sort + \(n\) binary searches: \(\Theta(n \log n)\).

interval123456
\((s_i, f_i)\)(0,3)(1,5)(4,7)(3,8)(2,9)(6,10)
\(w_i\)244726
\(p(s_i)\)112213
OPT(i)2469910

\(\text{OPT}(6) = \max\{9,\ 6 + \text{OPT}(2)\} = \max\{9, 10\} = 10\): take \(\ell_2, \ell_6\). Touching endpoints do not conflict (\(\ell_1\) ends at 3, \(\ell_4\) starts at 3).

10 · Binomial coefficients

\(C(n, k) = C(n-1, k-1) + C(n-1, k)\), \(C(n, 0) = C(n, n) = 1\). Fill rows \(0..n\), columns \(0..\min(i, k)\). \(\Theta(nk)\) time and space (one row updated right to left gives \(\Theta(k)\) space).

i \ j0123
01
111
2121
31331
41464
5151010

11 · Rod cutting (CLRS) and HW4 P6

$$r(j) = \max_{1 \le i \le j}\{p_i + r(j - i)\},\qquad r(0) = 0$$

\(r(j)\) = max revenue from a rod of length \(j\). Guess the length \(i\) of the first piece; the rest is cut optimally. \(n\) subproblems × \(O(n)\) = \(O(n^2)\).

HW4 P6 (each cut costs \(c\)). \(r(j)\) = max revenue minus cut costs for length \(j\). Either sell the rod whole (no cut), or cut off a first piece of length \(i < j\): that is one cut, and the remainder's own cuts are already charged inside \(r(j - i)\).

$$r(j) = \max\Big(p_j,\ \max_{1 \le i < j}\{p_i + r(j - i) - c\}\Big),\qquad r(0) = 0$$
procedure cutRodWithCost(p[1..n], c)
r[0] = 0
for j = 1 to n:
    best = p[j]; first[j] = j            (no cut)
    for i = 1 to j − 1:
        if p[i] + r[j − i] − c > best:
            best = p[i] + r[j − i] − c; first[j] = i
    r[j] = best
return r[n]            (pieces: first[n], then repeat on n − first[n])

\(O(n^2)\) time, \(O(n)\) space. Correct because every cutting either has no cut or has a first piece \(i\), and the cuts on the rest must be optimal for length \(j - i\) (cut and paste). The subtle point: do not subtract \(c\) in the no-cut case.

CLRS prices, checked against brute force over all cut sets:

length j12345678
\(p_j\)158910171720
\(r(j)\), c = 01581013171822
\(r(j)\), c = 2158911171720

Example: \(c = 2\), \(j = 4\): whole = 9; 2+2 = 5 + 5 − 2 = 8; 1+3 = 1 + 8 − 2 = 7. So \(r(4) = 9\) (with \(c = 0\) it was 10 from 2+2).

12 · DPV exercises: clean exam answers

DPV 6.1: maximum-sum contiguous subsequence, \(O(n)\)

5, 15, −30, 10, −5, 40, 10 → \(M\) = 5, 20, 0, 10, 5, 45, 55. Answer 55 (10, −5, 40, 10).

DPV 6.2 / HW4 P7: hotels, penalty \((300 - x)^2\)

Check: hotels at 200, 350, 550, 650, 900 → \(P\) = 10000, 2500, 12500, 2500, 5000. Stops 350, 650, 900 (days of 350, 300, 250: \(2500 + 0 + 2500 = 5000\)). Brute force agrees. (DPV's original uses 200 instead of 300; same algorithm.)

DPV 6.3: Yuckdonald's

Check: \(m\) = 2, 4, 5, 9, 10; \(p\) = 6, 8, 5, 7, 4; \(k = 4\). prev = 0, 0, 0, 3, 3; \(P\) = 6, 8, 8, 15, 15. Answer 15 (miles 4 and 9).

DPV 6.4: word break

Check: "itwasthebest" with dict {it, was, the, best, be, st, a, i, of, times} → \(S(12)\) true, words: it | was | the | best.

DPV 6.7: longest palindromic subsequence, \(O(n^2)\)

Check: DPV's sequence A, C, G, T, G, T, C, A, A, A, A, T, C, G → 8 (e.g. C T A A A A T C). Brute force agrees.

DPV 6.8: longest common substring, \(O(mn)\)

–BABCA
–000000
A001001
B010200
A002001
B010300
C000040

x = ABABC, y = BABCA → 4 (BABC). Contrast with LCS: there the mismatch case takes a max instead of resetting to 0.

DPV 6.9: cutting a string (interval DP)

Check: \(n = 20\), cuts 3, 10 → 30 (cut 10 first: 20 + 10), matching DPV. \(n = 10\), cuts 2, 4, 7 → 20. Both confirmed by trying every cut order.

Self-check

1. Why is LIS defined as "ending exactly at j" and not "best among the first j"?

To extend a subsequence by \(a_j\) you must know its last element is \(< a_j\). "Ending at j" records that last element; "best among the first j" does not, so no valid recurrence exists for it. Answer is then \(\max_j L(j)\), not \(L(n)\).

2. In the 1-D 0/1 knapsack loop, what goes wrong if w runs upward?

\(B[w - w_k]\) may already include item \(k\) from this same pass, so item \(k\) can be taken repeatedly. You get knapsack with repetition (DPV example: 48 instead of 46).

3. The knapsack DP is \(O(nW)\) but knapsack is NP-hard. Why no contradiction?

\(O(nW)\) is pseudo-polynomial: input size counts the bits of \(W\), about \(\log W\), so \(W = 2^{\text{bits}}\) is exponential in input size.

4. Edit distance of kitten → sitting? Subproblem count and time for strings of lengths m, n?

3 (substitute k→s, substitute e→i, insert g). \((m+1)(n+1)\) subproblems, \(O(1)\) each, \(O(mn)\).

5. Rod cutting with cut cost \(c = 2\), CLRS prices. What is \(r(5)\) and which cut achieves it?

\(r(5) = 11\): pieces 2 + 3 give \(5 + 8 - 2 = 11\), beating the whole rod (10) and 1 + 4 (\(1 + 9 - 2 = 8\)).

6. Chain matrix multiplication: which fill order is invalid, and what is the running time?

Rows top to bottom (\(i = 1, 2, \dots\)) is invalid, since \(C(i, j)\) reads \(C(k+1, j)\) in a lower row. Fill by increasing length (or rows bottom to top). \(O(n^2)\) subproblems × \(O(n)\) splits = \(O(n^3)\).