Dynamic Programming




CS146

Chris Pollett

Apr 23, 2014

Outline

Introduction

Non-DP Cord-Cutting Analysis

Here is our cord-cutting code from Monday:

CUT-ROD(p,n)
1 if n == 0
2     return 0
3 q = - infty
4 for i = 1 to n
5     q = max( q, p[i] + CUT-ROD(p, n-i ))
6 return q
Recursive calls to CUT-ROD

Rod-Cutting via Dynamic Programming

MEMOIZED-CUT-ROD

Here is the pseudo-code for the top-down approach. We use the array `r` to remember solutions to sub-problems. Before we compute a sub-problem we check if `r` has a value, if it does, we return what's stored in `r`; otherwise, we compute sub-problem.

MEMOIZED-CUT-ROD(p,n)
1 let r[0..n] be a new array
2 for i = 0 to n
3    r[i] = -infty // initialize subproblem solutions to sentinel value
4 return MEMOIZED-CUT-ROD-AUX(p,n,r)
MEMOIZED-CUT-ROD-AUX(p, n, r)
1 if r[n] ≥ 0
2    return r[n]
3 if n == 0
4    q = 0
5 else q = -infty
6    for i = 1 to n
7       q = max(q, p[i] + MEMOIZED-CUT-ROD-AUX(p, n - i, r))
8 r[n] = q
9 return q

BOTTOM-UP-CUT-ROD(p,n)

The bottom up procedure is especially easy for CUT-ROD as the order in which we were already making the sub-calls for different `j` values was sorted from smaller to larger.

1 let r[0..n] be a new array
3 for j = 0 to n // j represents problem size solved so far
4    q = 0
5    for(i = 1 to j)
6        q = max(q, p[i] + r[j - i])
7    r[j] = q
8 return r[n]

Both top-down and bottom up approaches for rod cutting have the same asymptotic run-time, `Theta(n^2)`. For bottom up it is easier to see... we have nested for loops with constant time work inside. For top down we have an outer loop that execute `n` times, the first time it calls the `n-1` subproblem and then for the remainder of the loop uses O(1) look-up to find values. So it satisfies a recurrence `T(n) = T(n-1) + Theta(n - 1)`. So will be `Theta(n^2)`.

Subproblem Graphs

Rod Cutting n=4 subproblem graph

Reconstructing a solution

PRINT-CUT-ROD-SOLUTION

PRINT-CUT-ROD-SOLUTION(p,n)
1 (r,s) = EXTENDED-BOTTOM-UP-CUT-ROD(p,n)
2 while n > 0
3    print s[n]
4    n = n - s[n]
EXTENDED-BOTTOM-UP-CUT-ROD(p, n)
01 let r[0..n] and s[0..n] be new arrays
02 r[0] = 0
03 for j = 1 to n
04    q = -infty
05    for i = 1 to j
06       if q < p[i] + r[j - i]
07            q = p[i] + r[j - i]
08            s[j] = i // record the best 1st split for each subproblem 
09    r[j] = q
10 return r and s

Longest Common Subsequence

Formalizing the LCS

Step 1: Characterizing an LCS