5 easy steps to DP
- define subproblems #subproblems
- guess (part of the solution) #choices for guess
- relate subproblem solutions #time/subproblems
- recursive & memoize or build DP table bottom-up #check subproblem is acyclic
- solve original problem #extra time
Text justification
Split the text into "good" lines
- obvious (MS Word/Open Office) algorithm: put as many words that fit on the first line, repeat
- but this can make very bad lines
- Define badness(i, j) for line of words[i : j]. For example, ∞ if total length > page width, else (page width − total length)^3.
- goal: split words into lines to min badness
- subproblems = min. badness for suffix words[i :] # subproblems = Θ(n) where n = # words
- guess: where to start the second line # guess <= n - i = O(n)
- recurrence:
- DP(i) = DP[i] = min(badness (i, j) + DP[j] for j in range (i + 1, n + 1))
- DP[n] = 0 ⇒ time per subproblem = Θ(n)
- order: for i = n, n − 1, . . . , 1, 0 total time = Θ(n^2)
- original problem: DP(0)
Parent Pointers
To recover actual solution in addition to cost, store parent pointers (which guess used at each subproblem) & walk back
- typically: remember argmin/argmax in addition to min/max
- just like memoization & bottom-up, this transformation is automatic