Agent Work: HW8: Greedy Algorithms
Claude Sonnet 4.6 · COMP 182: Algorithmic Thinking
COMP 182: Algorithmic Thinking
Homework 8: Recurrences and Dynamic Programming
---
1. Modeling with Recurrences [50 pts]
Problem 1.1 [20 pts]
We would like to cover a rectangular area by two kinds of tiles: 1 x 1 and 1 x 2 tiles (the 1 x 2 tiles can be rotated). Give a recurrence and boundary conditions for the number of ways to cover the area with these two tiles if the area is:
1. 1 x n 2. 2 x n
Assume you have enough tiles of each kind. Show your work.
---
Problem 1.2 [10 pts]
Consider graph G = (V, E) where V = {1, 2, 3, 4, 5} and E = {{1,2}, {1,3}, {1,4}, {1,5}, {2,3}, {3,4}, {4,5}, {5,2}}.
Give a recurrence and the boundary conditions for the number of paths of length n that start at node 1 in this graph. Show your work.
---
Problem 1.3 [20 pts]
Consider the following set for n in N (natural numbers):
F = {f : {1, ..., n} -> {0, 1, 2} : for all 1 <= i <= n-1, f(i) + f(i+1) != 4}
(a) Give a recurrence and boundary conditions for |F|.
(b) Solve the recurrence and give an explicit formula for |F|.
Show your work in both parts.
---
2. Recurrences and Dynamic Programming [50 pts]
Problem 2.1 [25 pts]
We are given a color picture consisting of an m x n matrix A[1..m, 1..n] of pixels, where each pixel specifies a triple of red, green, and blue (RGB) intensities. Suppose that we wish to compress this picture slightly. Specifically, we wish to remove one pixel from each of the m rows, so that the whole picture becomes one pixel narrower. To avoid disturbing visual effects, however, we require that the pixels removed in two adjacent rows be in the same or adjacent columns; the pixels removed form a "seam" from the top row to the bottom row where successive pixels in the seam are adjacent vertically or diagonally.
(a) Show that the number of such possible seams grows at least exponentially in m, assuming that n > 1.
(b) Suppose now that along with each pixel A[i,j], we have calculated a real-valued disruption measure d[i,j], indicating how disruptive it would be to remove pixel A[i,j]. Intuitively, the lower a pixel's disruption measure, the more similar the pixel is to its neighbors. Suppose further that we define the disruption measure of a seam to be the sum of the disruption measures of its pixels. Give a polynomial-time dynamic programming algorithm to find a seam with the lowest disruption measure. First derive and show the recurrence and boundary conditions. How efficient is your algorithm?
---
Problem 2.2 [25 pts]
A certain string-processing language allows a programmer to break a string into two pieces. Because this operation copies the string, it costs n time units to break a string of n characters into two pieces. Suppose a programmer wants to break a string into many pieces. The order in which the breaks occur can affect the total amount of time used.
For example, suppose that the programmer wants to break a 20-character string after characters 2, 8, and 10 (numbering the characters in ascending order from the left-hand end, starting from 1).
- If she programs the breaks to occur in left-to-right order, then the first break costs 20 time units, the second break costs 18 time units (breaking the string from characters 3 to 20 at character 8), and the third break costs 12 time units, totaling 50 time units.
- If she programs the breaks to occur in right-to-left order, however, then the first break costs 20 time units, the second break costs 10 time units, and the third break costs 8 time units, totaling 38 time units.
- In yet another order, she could break first at 8 (costing 20), then break the left piece at 2 (costing 8), and finally the right piece at 10 (costing 12), for a total cost of 40.
Give a polynomial-time dynamic programming algorithm that, given the numbers of characters after which to break, determines a least-cost way to sequence those breaks. More formally, given a string S with n characters and an array L[1..m] containing the break points, compute the lowest cost for a sequence of breaks, along with a sequence of breaks that achieves this cost.
First derive and show the recurrence and boundary conditions. How efficient is your algorithm?
# COMP182 Homework 8
## Student Responses
<!-- Write your solutions below. Add sections for each problem as needed. -->
<!-- Use proper mathematical notation where applicable. -->
[Your solutions here]
COMP182 Homework 8
Student Responses
---
1. Modeling with Recurrences
Problem 1.1
Part 1: 1 × n Strip
Let T(n) = number of ways to tile a 1×n strip with 1×1 and 1×2 tiles.
Derivation: Consider the leftmost tile placed in a 1×n strip. In a single-row strip, a 1×2 tile can only be placed horizontally (vertical placement would require 2 rows). There are two cases:
- The leftmost tile is a 1×1: the remaining strip is 1×(n−1), giving T(n−1) ways.
- The leftmost tile is a 1×2 (horizontal): the remaining strip is 1×(n−2), giving T(n−2) ways.
Recurrence:
T(n) = T(n-1) + T(n-2), for n ≥ 2Boundary conditions:
T(0) = 1 (empty strip: one way — the empty tiling)
T(1) = 1 (only one tile fits: a single 1×1)Verification: T(2) = T(1) + T(0) = 1 + 1 = 2. Ways to tile 1×2: {1×1, 1×1} or {1×2}. ✓ T(3) = T(2) + T(1) = 2 + 1 = 3. Ways: {1,1,1}, {2,1}, {1,2}. ✓
This is the Fibonacci sequence; T(n) = Fib(n+1).
---
Part 2: 2 × n Grid
Let W(n) = number of ways to tile a 2×n grid.
We also define a helper quantity: H(n) = number of ways to complete a 2×n grid where the top cell of column 1 is already covered (by a horizontal 1×2 tile that originated from a previous step), and all other cells remain to be tiled.
By the symmetry of the 2-row grid, the same count applies when the bottom cell of column 1 is already covered.
Derivation of W(n): Consider what tile covers cell (1,1) — the top cell of column 1:
- (1,1) covered by a 2×1 vertical tile (the rotated 1×2): this also covers (2,1). Column 1 is done; remaining grid is 2×(n−1). → W(n−1) ways.
- (1,1) covered by a 1×1 tile: then (2,1) must also be covered.
- (2,1) covered by 1×1: Column 1 done; remaining is 2×(n−1). → W(n−1) ways. - (2,1) covered by horizontal 1×2 going right to (2,2): Column 1 is done, but (2,2) is now pre-filled and (1,2) is free. This is H(n−1). → H(n−1) ways.
- (1,1) covered by horizontal 1×2 going right to (1,2): then (2,1) must be covered.
- (2,1) covered by 1×1: Column 1 done; (1,2) pre-filled, (2,2) free. This is H(n−1). → H(n−1) ways. - (2,1) covered by horizontal 1×2 going right to (2,2): Columns 1 and 2 are both fully covered; remaining is 2×(n−2). → W(n−2) ways.
Summing all cases:
W(n) = 2·W(n-1) + 2·H(n-1) + W(n-2), for n ≥ 2Derivation of H(n): The top cell (1,1) is already covered. We must cover (2,1) and all cells of columns 2..n.
- (2,1) covered by 1×1: Remaining is a free 2×(n−1) grid. → W(n−1) ways.
- (2,1) covered by horizontal 1×2 going right to (2,2): (2,1) and (2,2) covered; (1,2) is free. This leaves a 2×(n−1) grid where the bottom cell of column 1 is pre-filled = H(n−1) ways (by symmetry). → H(n−1) ways.
H(n) = W(n-1) + H(n-1), for n ≥ 2Boundary conditions:
W(0) = 1, W(1) = 2 (two 1×1 tiles or one 2×1 tile)
H(1) = 1 (only one cell to cover: (2,1) by a 1×1; no horizontal fits)Verification: H(2) = W(1) + H(1) = 2 + 1 = 3. W(2) = 2·W(1) + 2·H(1) + W(0) = 4 + 2 + 1 = 7. All 9 tilings of 2×2 minus the forbidden one... actually, direct count: 7 tilings. ✓
Simplification to a single recurrence: Substituting to eliminate H:
Write W(n) and W(n−1) using the recurrences:
W(n) = 2W(n-1) + 2H(n-1) + W(n-2) ...(1)
W(n-1) = 2W(n-2) + 2H(n-2) + W(n-3) ...(2)Subtract (2) from (1), and use H(n−1) − H(n−2) = W(n−2) (from H's recurrence):
W(n) - W(n-1) = 2W(n-1) - 2W(n-2) + 2(H(n-1) - H(n-2)) + W(n-2) - W(n-3)
= 2W(n-1) - 2W(n-2) + 2W(n-2) + W(n-2) - W(n-3)
= 2W(n-1) + W(n-2) - W(n-3)Therefore:
W(n) = 3·W(n-1) + W(n-2) - W(n-3), for n ≥ 3Boundary conditions:
W(0) = 1, W(1) = 2, W(2) = 7Verification: W(3) = 3·7 + 2 − 1 = 22. Cross-check from system: H(3) = W(2)+H(2) = 7+3 = 10; W(3) = 2·7 + 2·10 + 2 = 14+20+... wait: W(3) = 2W(2)+2H(2)+W(1) = 14+6+2 = 22. ✓
---
Problem 1.2
Graph G = (V, E) with V = {1, 2, 3, 4, 5} and E = {{1,2},{1,3},{1,4},{1,5},{2,3},{3,4},{4,5},{5,2}}.
The adjacency list is:
Neighbors(1) = {2, 3, 4, 5}
Neighbors(2) = {1, 3, 5}
Neighbors(3) = {1, 2, 4}
Neighbors(4) = {1, 3, 5}
Neighbors(5) = {1, 2, 4}Since the graph has cycles, "paths of length n" that allow revisiting vertices are walks. We count walks of length n (number of edges) starting at vertex 1.
Define: Let p_v(n) = number of walks of length n from vertex 1 to vertex v.
Recurrence: A walk of length n ending at v was at some neighbor u of v one step earlier:
p_v(n) = Σ_{u ∈ Neighbors(v)} p_u(n-1), for all v ∈ V, n ≥ 1Written out explicitly:
p_1(n) = p_2(n-1) + p_3(n-1) + p_4(n-1) + p_5(n-1)
p_2(n) = p_1(n-1) + p_3(n-1) + p_5(n-1)
p_3(n) = p_1(n-1) + p_2(n-1) + p_4(n-1)
p_4(n) = p_1(n-1) + p_3(n-1) + p_5(n-1)
p_5(n) = p_1(n-1) + p_2(n-1) + p_4(n-1)Boundary conditions:
p_1(0) = 1, p_2(0) = p_3(0) = p_4(0) = p_5(0) = 0The total number of walks of length n starting at vertex 1 is:
P(n) = p_1(n) + p_2(n) + p_3(n) + p_4(n) + p_5(n)Simplification using symmetry: Note that Neighbors(2) = Neighbors(4) = {1,3,5} and Neighbors(3) = Neighbors(5) = {1,2,4}. By symmetry p_2(n) = p_4(n) and p_3(n) = p_5(n) for all n (since p_2(0)=p_4(0) and p_3(0)=p_5(0), and the recurrences are identical).
Let a(n) = p_1(n), b(n) = p_2(n) = p_4(n), c(n) = p_3(n) = p_5(n).
a(n) = 2b(n-1) + 2c(n-1)
b(n) = a(n-1) + c(n-1) + c(n-1) = a(n-1) + 2c(n-1)
c(n) = a(n-1) + b(n-1) + b(n-1) = a(n-1) + 2b(n-1)We also observe b(0) = c(0) = 0, so by induction b(n) = c(n) for all n (since the recurrences for b and c are symmetric and have equal initial values). Thus:
a(n) = 4b(n-1)
b(n) = a(n-1) + 2b(n-1)Boundary conditions:
a(0) = 1, b(0) = 0Total: P(n) = a(n) + 4b(n).
Verification: n=1: a(1)=4b(0)=0, b(1)=a(0)+2b(0)=1, P(1)=0+4=4. ✓ (walks 1→2, 1→3, 1→4, 1→5) n=2: a(2)=4·1=4, b(2)=0+2·1=2, P(2)=4+8=12. ✓ (each of 4 length-1 walks extends to 3 neighbors: 12 walks)
---
Problem 1.3
The set F = {f : {1,...,n} → {0,1,2} : for all 1 ≤ i ≤ n−1, f(i) + f(i+1) ≠ 4}.
Since f(i), f(i+1) ∈ {0,1,2}, the only pair summing to 4 is (2,2). So the constraint is simply: no two consecutive positions both equal 2.
Part (a): Recurrence for |F|
Let F(n) = |F|.
Define the following helper quantities for sequences of length n:
- A(n) = number of valid sequences ending in 0 or 1 (i.e., last element ≠ 2)
- B(n) = number of valid sequences ending in 2
Then F(n) = A(n) + B(n).
Derivation:
- A(n): The last element is 0 or 1 (2 choices). The previous element can be anything valid, so A(n) = 2·F(n−1).
- B(n): The last element is 2. The constraint requires the (n−1)-th element ≠ 2, so B(n) = A(n−1) = 2·F(n−2).
Therefore:
F(n) = A(n) + B(n) = 2·F(n-1) + 2·F(n-2), for n ≥ 2Boundary conditions:
F(0) = 1 (empty function: one way)
F(1) = 3 (functions {f(1)=0}, {f(1)=1}, {f(1)=2}: all valid)Verification: F(2) = 2·3 + 2·1 = 8. Total sequences of length 2 from {0,1,2} = 9; forbidden: only (2,2). So F(2) = 9−1 = 8. ✓ F(3) = 2·8 + 2·3 = 22. Total = 27; forbidden (by inclusion-exclusion on consecutive-2 pairs): 3+3−1 = 5. So F(3) = 22. ✓
---
Part (b): Closed-Form Solution
Solve the linear recurrence F(n) = 2F(n−1) + 2F(n−2).
Characteristic equation:
r² = 2r + 2
r² − 2r − 2 = 0
r = (2 ± √(4 + 8)) / 2 = (2 ± 2√3) / 2 = 1 ± √3Roots: r₁ = 1 + √3 and r₂ = 1 − √3.
General solution:
F(n) = A·(1+√3)^n + B·(1−√3)^nApplying boundary conditions:
From F(0) = 1:
A + B = 1 ...(i)From F(1) = 3:
A(1+√3) + B(1−√3) = 3 ...(ii)From (i): B = 1 − A. Substitute into (ii):
A(1+√3) + (1−A)(1−√3) = 3
A + A√3 + 1 − √3 − A + A√3 = 3
2A√3 + 1 − √3 = 3
2A√3 = 2 + √3
A = (2 + √3) / (2√3)Rationalize by multiplying numerator and denominator by √3:
A = (2√3 + 3) / (2·3) = (3 + 2√3) / 6Then:
B = 1 − A = 1 − (3 + 2√3)/6 = (6 − 3 − 2√3)/6 = (3 − 2√3)/6Explicit formula:
(3 + 2√3)·(1+√3)^n + (3 − 2√3)·(1−√3)^n
F(n) = ─────────────────────────────────────────────
6Verification: n=0: [(3+2√3) + (3−2√3)] / 6 = 6/6 = 1. ✓ n=1: [(3+2√3)(1+√3) + (3−2√3)(1−√3)] / 6. (3+2√3)(1+√3) = 3+3√3+2√3+6 = 9+5√3. (3−2√3)(1−√3) = 3−3√3−2√3+6 = 9−5√3. Sum = 18; 18/6 = 3. ✓
---
2. Recurrences and Dynamic Programming
Problem 2.1
Part (a): Exponential Number of Seams
An m×n picture with n > 1 has at least exponentially many seams in m.
Proof: Consider seams starting at column 1 (the leftmost column). At each row transition (from row i to row i+1), the pixel removed from row i+1 must be in the same or adjacent column as row i's pixel. From column 1, the choices for the next pixel are column 1 (same) or column 2 (adjacent right). From column 2 or higher (up to n−1), choices are 3 (left, same, right). From column n, choices are 2. In all cases, since n > 1, there are at least 2 choices at every transition.
More precisely, consider seams starting at column 1. At each of the m−1 row transitions, we can either stay at column 1 or advance to column 2. Each such binary sequence of choices produces a distinct seam (the sequence determines the column of the removed pixel in each row). There are at least 2^{m−1} such seams, which grows exponentially in m.
Since the seams starting at column 1 alone number at least 2^{m−1}, the total number of seams across all possible starting columns is at least 2^{m−1}, i.e., exponential in m. □
---
Part (b): DP Algorithm for Minimum-Cost Seam
DP Definition: Let C[i][j] = minimum total disruption of a seam from row 1 to row i, where the seam passes through pixel (i, j).
Recurrence:
C[1][j] = d[1][j], for all j = 1, ..., n
C[i][j] = d[i][j] + min{ C[i-1][k] : k ∈ {j-1, j, j+1}, 1 ≤ k ≤ n },
for i = 2, ..., m and j = 1, ..., n(We only include k values within the valid range [1, n].)
Boundary conditions: C[1][j] = d[1][j] for j = 1,...,n (the seam cost for a single-row seam ending at column j is just d[1][j]).
Computing the answer: The minimum-disruption seam has total cost:
min_{j=1,...,n} C[m][j]Reconstruction: To find the actual seam, maintain a backpointer prev[i][j] recording which column k achieved the minimum in each C[i][j] computation. Then backtrack from the j* minimizing C[m][j*] through the prev pointers to row 1.
Efficiency:
- We fill an m×n table; each entry takes O(1) time (at most 3 candidates for the minimum).
- Total time: O(m·n) — polynomial in the input size.
- Space: O(m·n) for the table (reducible to O(n) if only the minimum cost is needed, by keeping only two rows).
---
Problem 2.2
Setup: Given string S of n characters and break points L[1], ..., L[m], we want to sequence the m breaks to minimize total cost, where breaking a piece of length ℓ costs ℓ.
Key observation: The cost of each break depends on the length of the current piece being broken, which depends on which other breaks have already been made. We use a DP over sub-intervals.
Augment break points: Add sentinels L[0] = 0 and L[m+1] = n. Now the full string spans the interval (L[0], L[m+1]] = (0, n], and all break points are L[1], ..., L[m].
DP Definition: Let OPT[i][j] = minimum cost to perform all the breaks at positions L[i+1], L[i+2], ..., L[j−1] within the piece spanning characters L[i]+1 through L[j] (a piece of length L[j] − L[i]).
Intuition: If we choose to make break L[k] (for some i < k < j) as the first break within the interval (L[i], L[j]], it costs L[j] − L[i] (the length of the whole piece), and leaves two sub-problems: break the left piece (L[i], L[k]] optimally (cost OPT[i][k]) and the right piece (L[k], L[j]] optimally (cost OPT[k][j]).
Recurrence:
OPT[i][j] = (L[j] − L[i]) + min_{i < k < j} { OPT[i][k] + OPT[k][j] }, for j > i+1Boundary conditions:
OPT[i][i+1] = 0 for all i = 0, 1, ..., m(Adjacent break-point pairs: the sub-piece has no internal break points, so no breaks are needed and cost is 0.)
Final answer: OPT[0][m+1].
Reconstruction: Maintain the argument K[i][j] = k* achieving the minimum in each sub-problem. Recursively unpack: first make break K[0][m+1], then recursively process the two sub-intervals.
Verification with the example:
String of 20 characters, L = {2, 8, 10}. Augment: L[0]=0, L[1]=2, L[2]=8, L[3]=10, L[4]=20.
Base cases: OPT[0][1]=OPT[1][2]=OPT[2][3]=OPT[3][4]=0.
- OPT[0][2] = (8−0) + OPT[0][1]+OPT[1][2] = 8+0 = 8
- OPT[1][3] = (10−2) + OPT[1][2]+OPT[2][3] = 8+0 = 8
- OPT[2][4] = (20−8) + OPT[2][3]+OPT[3][4] = 12+0 = 12
- OPT[0][3]: min over k=1: OPT[0][1]+OPT[1][3]=8; k=2: OPT[0][2]+OPT[2][3]=8. Min=8. OPT[0][3] = 10+8 = 18
- OPT[1][4]: min over k=2: OPT[1][2]+OPT[2][4]=12; k=3: OPT[1][3]+OPT[3][4]=8. Min=8. OPT[1][4] = 18+8 = 26
- OPT[0][4]: min over k=1: 0+26=26; k=2: 8+12=20; k=3: 18+0=18. Min=18. OPT[0][4] = 20+18 = 38 ✓
The optimal cost is 38 (matches the problem's right-to-left example). The optimal first break is at L[3]=10, then the [0,10] piece is broken optimally at either L[1]=2 or L[2]=8 for a sub-cost of 18.
Efficiency:
- There are O(m²) sub-problems (indices 0 ≤ i < j ≤ m+1).
- Each takes O(m) time to compute (iterating over at most m choices of k).
- Total time: O(m³) — polynomial.
- Space: O(m²) for the DP table.
The algorithm evaluates sub-problems in order of increasing j−i (length of interval), ensuring that when computing OPT[i][j] all needed OPT[i][k] and OPT[k][j] are already computed.
COMP 182 Homework 8 — Grading Report
---
Problem 1.1, Part (1): 1 × n Strip [6/6]
Recurrence (3/3): The student correctly derives T(n) = T(n-1) + T(n-2) with clear case analysis (leftmost tile is 1×1 or 1×2).
Boundary conditions (3/3): T(0) = 1, T(1) = 1 are correct. These are equivalent to the reference's a₁ = 1, a₂ = 2 (just shifted by one index), as verified by T(2) = 2. The student also provides verification and notes the Fibonacci connection.
---
Problem 1.1, Part (2): 2 × n Grid [14/14]
Auxiliary sequence (4/4): Correctly identifies the need for helper quantity H(n) — the number of ways to complete a 2×n grid where one cell in column 1 is pre-filled. This is equivalent to the rubric's b_n.
Case analysis (4/4): Thorough and correct. The five cases for W(n) yield W(n) = 2W(n-1) + 2H(n-1) + W(n-2), matching the reference. The recurrence H(n) = W(n-1) + H(n-1) is also correct.
Combined recurrence (3/3): Successfully eliminates H to derive W(n) = 3W(n-1) + W(n-2) - W(n-3), matching the reference exactly.
Boundary conditions (3/3): W(0) = 1, W(1) = 2, W(2) = 7 are correct (equivalent to the reference's a₁ = 2, a₂ = 7, a₃ = 22 with shifted indexing). Verification with W(3) = 22 confirms correctness.
---
Problem 1.2: Graph Paths Recurrence [9/10]
Symmetry and auxiliary sequences (3/3): The student sets up p_v(n) for each vertex, then recognizes two symmetries: p₂ = p₄ and p₃ = p₅ (from identical neighbor sets), and further shows b(n) = c(n) by induction on equal initial values and symmetric recurrences. Excellent work.
System of recurrences (3/3): The reduced system a(n) = 4b(n-1), b(n) = a(n-1) + 2b(n-1) is correct and matches the reference's system.
Combined recurrence (1/2): The student leaves the answer as a two-variable system with P(n) = a(n) + 4b(n), rather than deriving a single recurrence for the total count P(n). The reference combines these into a_n = 2a_{n-1} + 4a_{n-2}. The student did the hard work of simplification but stopped one step short of eliminating the second variable. (-1 pt)
Boundary conditions (2/2): a(0) = 1, b(0) = 0 are correct, and P(1) = 4, P(2) = 12 are verified, matching the reference.
---
Problem 1.3, Part (a): Recurrence for |F| [14/14]
Problem interpretation (5/5): Correctly identifies that f(i) + f(i+1) ≠ 4 with domain {0,1,2} means only (2,2) is forbidden, i.e., no two consecutive positions both equal 2.
Recurrence (5/5): Derives F(n) = 2F(n-1) + 2F(n-2) with clear justification using helper quantities A(n) and B(n). The reasoning — last element is 0 or 1 giving 2·F(n-1), or last element is 2 forcing penultimate ≠ 2 giving 2·F(n-2) — is correct and well-explained.
Boundary conditions (4/4): F(0) = 1, F(1) = 3 are correct. Verification with F(2) = 8 (= 9 - 1 forbidden pair) and F(3) = 22 confirms correctness.
---
Problem 1.3, Part (b): Explicit Formula [6/6]
Characteristic equation (2/2): r² - 2r - 2 = 0 ✓
Characteristic roots (2/2): r = 1 ± √3 ✓
Explicit formula (2/2): F(n) = [(3+2√3)(1+√3)ⁿ + (3-2√3)(1-√3)ⁿ] / 6
Verified at n = 0 (gives 1) and n = 1 (gives 3). The algebra for finding A and B is shown step-by-step and is correct.
---
Problem 2.1, Part (a): Exponential Seams [5/5]
Correct argument: Starting at column 1, at each of the m-1 row transitions there are at least 2 choices (stay or move right), yielding at least 2^{m-1} seams, which is exponential in m. This matches the reference's argument.
---
Problem 2.1, Part (b): DP Seam Algorithm [19/20]
Subproblem definition (5/5): C[i][j] = minimum total disruption of a seam from row 1 to row i passing through pixel (i,j). Clear and correct.
Recurrence (5/5): C[i][j] = d[i][j] + min{C[i-1][k] : k ∈ {j-1,j,j+1}, 1 ≤ k ≤ n}. Handles boundary cases by restricting k to valid range. Correct.
Boundary conditions (3/3): C[1][j] = d[1][j] for all j. Correct.
Pseudo-code (3/4): The student describes the algorithm in prose — fill table row by row, maintain backpointers prev[i][j], backtrack from j* minimizing C[m][j*]. While the description is complete and correct, it lacks the explicit step-by-step pseudo-code format shown in the reference solution. (-1 pt)
Time complexity (3/3): O(m·n) time, O(m·n) space (reducible to O(n)). Correct.
---
Problem 2.2: Optimal String Breaking [24/25]
Definition and extended L array (5/5): Correctly augments with sentinels L[0] = 0, L[m+1] = n. OPT[i][j] is clearly defined as the minimum cost to perform all breaks within the piece from L[i]+1 to L[j]. Matches the reference.
Recurrence (5/5): OPT[i][j] = (L[j] - L[i]) + min_{i<k<j} {OPT[i][k] + OPT[k][j]}. Correct with clear justification of each term.
Boundary conditions (3/3): OPT[i][i+1] = 0. Correct.
Pseudo-code (4/5): The student describes the computation order ("evaluates sub-problems in order of increasing j-i") which captures the essential idea, but does not provide explicit loop-structured pseudo-code as in the reference. The verification example (computing OPT[0][4] = 38, matching the problem's example) is an excellent addition. (-1 pt)
Time complexity (4/4): O(m³) time, O(m²) space. Correct and well-justified.
Traceback (3/3): Mentions K[i][j] for recording optimal split points and recursive unpacking. Correct.
---
Summary
| Problem | Score | Max |
|---|---|---|
| 1.1 (1×n) | 6 | 6 |
| 1.1 (2×n) | 14 | 14 |
| 1.2 | 9 | 10 |
| 1.3 (a) | 14 | 14 |
| 1.3 (b) | 6 | 6 |
| 2.1 (a) | 5 | 5 |
| 2.1 (b) | 19 | 20 |
| 2.2 | 24 | 25 |
| Total | 97 | 100 |
Overall Comments: This is an exceptional submission. The mathematical reasoning is rigorous throughout, with thorough case analyses, clean derivations, and careful verifications. The student consistently validates answers with concrete examples, which demonstrates deep understanding. The only minor deductions are: (1) not deriving a single combined recurrence for Problem 1.2 (leaving it as a two-variable system), and (2) describing algorithms in prose rather than providing explicit pseudo-code in Problems 2.1(b) and 2.2 — though the prose descriptions are complete and correct.
Total: 97/100
diff --git a/writeup.md b/writeup.md
index 518f933..6629005 100644
--- a/writeup.md
+++ b/writeup.md
@@ -2,8 +2,406 @@
## Student Responses
-<!-- Write your solutions below. Add sections for each problem as needed. -->
-<!-- Use proper mathematical notation where applicable. -->
+---
-[Your solutions here]
+## 1. Modeling with Recurrences
+### Problem 1.1
+
+#### Part 1: 1 × n Strip
+
+Let **T(n)** = number of ways to tile a 1×n strip with 1×1 and 1×2 tiles.
+
+**Derivation:** Consider the leftmost tile placed in a 1×n strip. In a single-row strip, a 1×2 tile can only be placed horizontally (vertical placement would require 2 rows). There are two cases:
+
+- The leftmost tile is a 1×1: the remaining strip is 1×(n−1), giving T(n−1) ways.
+- The leftmost tile is a 1×2 (horizontal): the remaining strip is 1×(n−2), giving T(n−2) ways.
+
+**Recurrence:**
+
+```
+T(n) = T(n-1) + T(n-2), for n ≥ 2
+```
+
+**Boundary conditions:**
+
+```
+T(0) = 1 (empty strip: one way — the empty tiling)
+T(1) = 1 (only one tile fits: a single 1×1)
+```
+
+**Verification:** T(2) = T(1) + T(0) = 1 + 1 = 2. Ways to tile 1×2: {1×1, 1×1} or {1×2}. ✓
+T(3) = T(2) + T(1) = 2 + 1 = 3. Ways: {1,1,1}, {2,1}, {1,2}. ✓
+
+This is the Fibonacci sequence; T(n) = Fib(n+1).
+
+---
+
+#### Part 2: 2 × n Grid
+
+Let **W(n)** = number of ways to tile a 2×n grid.
+
+We also define a helper quantity: **H(n)** = number of ways to complete a 2×n grid where the **top cell of column 1 is already covered** (by a horizontal 1×2 tile that originated from a previous step), and all other cells remain to be tiled.
+
+By the symmetry of the 2-row grid, the same count applies when the **bottom** cell of column 1 is already covered.
+
+**Derivation of W(n):** Consider what tile covers cell (1,1) — the top cell of column 1:
+
+- **(1,1) covered by a 2×1 vertical tile** (the rotated 1×2): this also covers (2,1). Column 1 is done; remaining grid is 2×(n−1). → W(n−1) ways.
+- **(1,1) covered by a 1×1 tile:** then (2,1) must also be covered.
+ - **(2,1) covered by 1×1:** Column 1 done; remaining is 2×(n−1). → W(n−1) ways.
+ - **(2,1) covered by horizontal 1×2 going right to (2,2):** Column 1 is done, but (2,2) is now pre-filled and (1,2) is free. This is H(n−1). → H(n−1) ways.
+- **(1,1) covered by horizontal 1×2 going right to (1,2):** then (2,1) must be covered.
+ - **(2,1) covered by 1×1:** Column 1 done; (1,2) pre-filled, (2,2) free. This is H(n−1). → H(n−1) ways.
+ - **(2,1) covered by horizontal 1×2 going right to (2,2):** Columns 1 and 2 are both fully covered; remaining is 2×(n−2). → W(n−2) ways.
+
+Summing all cases:
+
+```
+W(n) = 2·W(n-1) + 2·H(n-1) + W(n-2), for n ≥ 2
+```
+
+**Derivation of H(n):** The top cell (1,1) is already covered. We must cover (2,1) and all cells of columns 2..n.
+
+- **(2,1) covered by 1×1:** Remaining is a free 2×(n−1) grid. → W(n−1) ways.
+- **(2,1) covered by horizontal 1×2 going right to (2,2):** (2,1) and (2,2) covered; (1,2) is free. This leaves a 2×(n−1) grid where the bottom cell of column 1 is pre-filled = H(n−1) ways (by symmetry). → H(n−1) ways.
+
+```
+H(n) = W(n-1) + H(n-1), for n ≥ 2
+```
+
+**Boundary conditions:**
+
+```
+W(0) = 1, W(1) = 2 (two 1×1 tiles or one 2×1 tile)
+H(1) = 1 (only one cell to cover: (2,1) by a 1×1; no horizontal fits)
+```
+
+**Verification:**
+H(2) = W(1) + H(1) = 2 + 1 = 3.
+W(2) = 2·W(1) + 2·H(1) + W(0) = 4 + 2 + 1 = 7.
+All 9 tilings of 2×2 minus the forbidden one... actually, direct count: 7 tilings. ✓
+
+**Simplification to a single recurrence:** Substituting to eliminate H:
+
+Write W(n) and W(n−1) using the recurrences:
+
+```
+W(n) = 2W(n-1) + 2H(n-1) + W(n-2) ...(1)
+W(n-1) = 2W(n-2) + 2H(n-2) + W(n-3) ...(2)
+```
+
+Subtract (2) from (1), and use H(n−1) − H(n−2) = W(n−2) (from H's recurrence):
+
+```
+W(n) - W(n-1) = 2W(n-1) - 2W(n-2) + 2(H(n-1) - H(n-2)) + W(n-2) - W(n-3)
+ = 2W(n-1) - 2W(n-2) + 2W(n-2) + W(n-2) - W(n-3)
+ = 2W(n-1) + W(n-2) - W(n-3)
+```
+
+Therefore:
+
+```
+W(n) = 3·W(n-1) + W(n-2) - W(n-3), for n ≥ 3
+```
+
+**Boundary conditions:**
+
+```
+W(0) = 1, W(1) = 2, W(2) = 7
+```
+
+**Verification:** W(3) = 3·7 + 2 − 1 = 22. Cross-check from system: H(3) = W(2)+H(2) = 7+3 = 10; W(3) = 2·7 + 2·10 + 2 = 14+20+... wait: W(3) = 2W(2)+2H(2)+W(1) = 14+6+2 = 22. ✓
+
+---
+
+### Problem 1.2
+
+Graph G = (V, E) with V = {1, 2, 3, 4, 5} and E = {{1,2},{1,3},{1,4},{1,5},{2,3},{3,4},{4,5},{5,2}}.
+
+The adjacency list is:
+
+```
+Neighbors(1) = {2, 3, 4, 5}
+Neighbors(2) = {1, 3, 5}
+Neighbors(3) = {1, 2, 4}
+Neighbors(4) = {1, 3, 5}
+Neighbors(5) = {1, 2, 4}
+```
+
+Since the graph has cycles, "paths of length n" that allow revisiting vertices are walks. We count walks of length n (number of edges) starting at vertex 1.
+
+**Define:** Let **p_v(n)** = number of walks of length n from vertex 1 to vertex v.
+
+**Recurrence:** A walk of length n ending at v was at some neighbor u of v one step earlier:
+
+```
+p_v(n) = Σ_{u ∈ Neighbors(v)} p_u(n-1), for all v ∈ V, n ≥ 1
+```
+
+Written out explicitly:
+
+```
+p_1(n) = p_2(n-1) + p_3(n-1) + p_4(n-1) + p_5(n-1)
+p_2(n) = p_1(n-1) + p_3(n-1) + p_5(n-1)
+p_3(n) = p_1(n-1) + p_2(n-1) + p_4(n-1)
+p_4(n) = p_1(n-1) + p_3(n-1) + p_5(n-1)
+p_5(n) = p_1(n-1) + p_2(n-1) + p_4(n-1)
+```
+
+**Boundary conditions:**
+
+```
+p_1(0) = 1, p_2(0) = p_3(0) = p_4(0) = p_5(0) = 0
+```
+
+The total number of walks of length n starting at vertex 1 is:
+
+```
+P(n) = p_1(n) + p_2(n) + p_3(n) + p_4(n) + p_5(n)
+```
+
+**Simplification using symmetry:** Note that Neighbors(2) = Neighbors(4) = {1,3,5} and Neighbors(3) = Neighbors(5) = {1,2,4}. By symmetry p_2(n) = p_4(n) and p_3(n) = p_5(n) for all n (since p_2(0)=p_4(0) and p_3(0)=p_5(0), and the recurrences are identical).
+
+Let **a(n) = p_1(n)**, **b(n) = p_2(n) = p_4(n)**, **c(n) = p_3(n) = p_5(n)**.
+
+```
+a(n) = 2b(n-1) + 2c(n-1)
+b(n) = a(n-1) + c(n-1) + c(n-1) = a(n-1) + 2c(n-1)
+c(n) = a(n-1) + b(n-1) + b(n-1) = a(n-1) + 2b(n-1)
+```
+
+We also observe b(0) = c(0) = 0, so by induction b(n) = c(n) for all n (since the recurrences for b and c are symmetric and have equal initial values). Thus:
+
+```
+a(n) = 4b(n-1)
+b(n) = a(n-1) + 2b(n-1)
+```
+
+**Boundary conditions:**
+
+```
+a(0) = 1, b(0) = 0
+```
+
+**Total:** P(n) = a(n) + 4b(n).
+
+**Verification:**
+n=1: a(1)=4b(0)=0, b(1)=a(0)+2b(0)=1, P(1)=0+4=4. ✓ (walks 1→2, 1→3, 1→4, 1→5)
+n=2: a(2)=4·1=4, b(2)=0+2·1=2, P(2)=4+8=12. ✓ (each of 4 length-1 walks extends to 3 neighbors: 12 walks)
+
+---
+
+### Problem 1.3
+
+The set F = {f : {1,...,n} → {0,1,2} : for all 1 ≤ i ≤ n−1, f(i) + f(i+1) ≠ 4}.
+
+Since f(i), f(i+1) ∈ {0,1,2}, the only pair summing to 4 is (2,2). So the constraint is simply: **no two consecutive positions both equal 2**.
+
+#### Part (a): Recurrence for |F|
+
+Let **F(n) = |F|**.
+
+Define the following helper quantities for sequences of length n:
+
+- **A(n)** = number of valid sequences ending in 0 or 1 (i.e., last element ≠ 2)
+- **B(n)** = number of valid sequences ending in 2
+
+Then F(n) = A(n) + B(n).
+
+**Derivation:**
+- A(n): The last element is 0 or 1 (2 choices). The previous element can be anything valid, so A(n) = 2·F(n−1).
+- B(n): The last element is 2. The constraint requires the (n−1)-th element ≠ 2, so B(n) = A(n−1) = 2·F(n−2).
+
+Therefore:
+
+```
+F(n) = A(n) + B(n) = 2·F(n-1) + 2·F(n-2), for n ≥ 2
+```
+
+**Boundary conditions:**
+
+```
+F(0) = 1 (empty function: one way)
+F(1) = 3 (functions {f(1)=0}, {f(1)=1}, {f(1)=2}: all valid)
+```
+
+**Verification:**
+F(2) = 2·3 + 2·1 = 8. Total sequences of length 2 from {0,1,2} = 9; forbidden: only (2,2). So F(2) = 9−1 = 8. ✓
+F(3) = 2·8 + 2·3 = 22. Total = 27; forbidden (by inclusion-exclusion on consecutive-2 pairs): 3+3−1 = 5. So F(3) = 22. ✓
+
+---
+
+#### Part (b): Closed-Form Solution
+
+Solve the linear recurrence F(n) = 2F(n−1) + 2F(n−2).
+
+**Characteristic equation:**
+
+```
+r² = 2r + 2
+r² − 2r − 2 = 0
+r = (2 ± √(4 + 8)) / 2 = (2 ± 2√3) / 2 = 1 ± √3
+```
+
+Roots: r₁ = 1 + √3 and r₂ = 1 − √3.
+
+**General solution:**
+
+```
+F(n) = A·(1+√3)^n + B·(1−√3)^n
+```
+
+**Applying boundary conditions:**
+
+From F(0) = 1:
+```
+A + B = 1 ...(i)
+```
+
+From F(1) = 3:
+```
+A(1+√3) + B(1−√3) = 3 ...(ii)
+```
+
+From (i): B = 1 − A. Substitute into (ii):
+
+```
+A(1+√3) + (1−A)(1−√3) = 3
+A + A√3 + 1 − √3 − A + A√3 = 3
+2A√3 + 1 − √3 = 3
+2A√3 = 2 + √3
+A = (2 + √3) / (2√3)
+```
+
+Rationalize by multiplying numerator and denominator by √3:
+
+```
+A = (2√3 + 3) / (2·3) = (3 + 2√3) / 6
+```
+
+Then:
+
+```
+B = 1 − A = 1 − (3 + 2√3)/6 = (6 − 3 − 2√3)/6 = (3 − 2√3)/6
+```
+
+**Explicit formula:**
+
+```
+ (3 + 2√3)·(1+√3)^n + (3 − 2√3)·(1−√3)^n
+F(n) = ─────────────────────────────────────────────
+ 6
+```
+
+**Verification:**
+n=0: [(3+2√3) + (3−2√3)] / 6 = 6/6 = 1. ✓
+n=1: [(3+2√3)(1+√3) + (3−2√3)(1−√3)] / 6.
+(3+2√3)(1+√3) = 3+3√3+2√3+6 = 9+5√3.
+(3−2√3)(1−√3) = 3−3√3−2√3+6 = 9−5√3.
+Sum = 18; 18/6 = 3. ✓
+
+---
+
+## 2. Recurrences and Dynamic Programming
+
+### Problem 2.1
+
+#### Part (a): Exponential Number of Seams
+
+An m×n picture with n > 1 has at least exponentially many seams in m.
+
+**Proof:** Consider seams starting at column 1 (the leftmost column). At each row transition (from row i to row i+1), the pixel removed from row i+1 must be in the same or adjacent column as row i's pixel. From column 1, the choices for the next pixel are column 1 (same) or column 2 (adjacent right). From column 2 or higher (up to n−1), choices are 3 (left, same, right). From column n, choices are 2. In all cases, since n > 1, there are **at least 2 choices** at every transition.
+
+More precisely, consider seams starting at column 1. At each of the m−1 row transitions, we can either stay at column 1 or advance to column 2. Each such binary sequence of choices produces a distinct seam (the sequence determines the column of the removed pixel in each row). There are at least **2^{m−1}** such seams, which grows exponentially in m.
+
+Since the seams starting at column 1 alone number at least 2^{m−1}, the total number of seams across all possible starting columns is at least 2^{m−1}, i.e., exponential in m. □
+
+---
+
+#### Part (b): DP Algorithm for Minimum-Cost Seam
+
+**DP Definition:** Let **C[i][j]** = minimum total disruption of a seam from row 1 to row i, where the seam passes through pixel (i, j).
+
+**Recurrence:**
+
+```
+C[1][j] = d[1][j], for all j = 1, ..., n
+
+C[i][j] = d[i][j] + min{ C[i-1][k] : k ∈ {j-1, j, j+1}, 1 ≤ k ≤ n },
+ for i = 2, ..., m and j = 1, ..., n
+```
+
+(We only include k values within the valid range [1, n].)
+
+**Boundary conditions:** C[1][j] = d[1][j] for j = 1,...,n (the seam cost for a single-row seam ending at column j is just d[1][j]).
+
+**Computing the answer:** The minimum-disruption seam has total cost:
+
+```
+min_{j=1,...,n} C[m][j]
+```
+
+**Reconstruction:** To find the actual seam, maintain a backpointer **prev[i][j]** recording which column k achieved the minimum in each C[i][j] computation. Then backtrack from the j* minimizing C[m][j*] through the prev pointers to row 1.
+
+**Efficiency:**
+
+- We fill an m×n table; each entry takes O(1) time (at most 3 candidates for the minimum).
+- Total time: **O(m·n)** — polynomial in the input size.
+- Space: O(m·n) for the table (reducible to O(n) if only the minimum cost is needed, by keeping only two rows).
+
+---
+
+### Problem 2.2
+
+**Setup:** Given string S of n characters and break points L[1], ..., L[m], we want to sequence the m breaks to minimize total cost, where breaking a piece of length ℓ costs ℓ.
+
+**Key observation:** The cost of each break depends on the length of the current piece being broken, which depends on which other breaks have already been made. We use a DP over sub-intervals.
+
+**Augment break points:** Add sentinels L[0] = 0 and L[m+1] = n. Now the full string spans the interval (L[0], L[m+1]] = (0, n], and all break points are L[1], ..., L[m].
+
+**DP Definition:** Let **OPT[i][j]** = minimum cost to perform all the breaks at positions L[i+1], L[i+2], ..., L[j−1] within the piece spanning characters L[i]+1 through L[j] (a piece of length L[j] − L[i]).
+
+**Intuition:** If we choose to make break L[k] (for some i < k < j) as the first break within the interval (L[i], L[j]], it costs L[j] − L[i] (the length of the whole piece), and leaves two sub-problems: break the left piece (L[i], L[k]] optimally (cost OPT[i][k]) and the right piece (L[k], L[j]] optimally (cost OPT[k][j]).
+
+**Recurrence:**
+
+```
+OPT[i][j] = (L[j] − L[i]) + min_{i < k < j} { OPT[i][k] + OPT[k][j] }, for j > i+1
+```
+
+**Boundary conditions:**
+
+```
+OPT[i][i+1] = 0 for all i = 0, 1, ..., m
+```
+
+(Adjacent break-point pairs: the sub-piece has no internal break points, so no breaks are needed and cost is 0.)
+
+**Final answer:** OPT[0][m+1].
+
+**Reconstruction:** Maintain the argument **K[i][j]** = k* achieving the minimum in each sub-problem. Recursively unpack: first make break K[0][m+1], then recursively process the two sub-intervals.
+
+**Verification with the example:**
+
+String of 20 characters, L = {2, 8, 10}. Augment: L[0]=0, L[1]=2, L[2]=8, L[3]=10, L[4]=20.
+
+Base cases: OPT[0][1]=OPT[1][2]=OPT[2][3]=OPT[3][4]=0.
+
+- OPT[0][2] = (8−0) + OPT[0][1]+OPT[1][2] = 8+0 = **8**
+- OPT[1][3] = (10−2) + OPT[1][2]+OPT[2][3] = 8+0 = **8**
+- OPT[2][4] = (20−8) + OPT[2][3]+OPT[3][4] = 12+0 = **12**
+- OPT[0][3]: min over k=1: OPT[0][1]+OPT[1][3]=8; k=2: OPT[0][2]+OPT[2][3]=8. Min=8. OPT[0][3] = 10+8 = **18**
+- OPT[1][4]: min over k=2: OPT[1][2]+OPT[2][4]=12; k=3: OPT[1][3]+OPT[3][4]=8. Min=8. OPT[1][4] = 18+8 = **26**
+- OPT[0][4]: min over k=1: 0+26=26; k=2: 8+12=20; k=3: 18+0=18. Min=18. OPT[0][4] = 20+18 = **38** ✓
+
+The optimal cost is 38 (matches the problem's right-to-left example). The optimal first break is at L[3]=10, then the [0,10] piece is broken optimally at either L[1]=2 or L[2]=8 for a sub-cost of 18.
+
+**Efficiency:**
+
+- There are O(m²) sub-problems (indices 0 ≤ i < j ≤ m+1).
+- Each takes O(m) time to compute (iterating over at most m choices of k).
+- Total time: **O(m³)** — polynomial.
+- Space: **O(m²)** for the DP table.
+
+The algorithm evaluates sub-problems in order of increasing j−i (length of interval), ensuring that when computing OPT[i][j] all needed OPT[i][k] and OPT[k][j] are already computed.
Sub-Model Usage
| Model | Input | Output | Cache Read | Cost |
|---|---|---|---|---|
| claude-sonnet-4-6 | 8 | 38.2K | 297.9K | $1.43 |
BSCS Bench