Dynamic Programming: Louis Siu 13.9.2007
Dynamic Programming: Louis Siu 13.9.2007
Louis Siu
13.9.2007
What is Dynamic
Programming (DP)?
Dynamic Programming
Idea
f(0) = 0
f(1) = 1
f(n) = f(n 1) + f(n 2), n > 1
Computing f(4)
f(4)
f(3)
f(2)
f(1)
f(2)
f(1)
f(1)
f(0)
f(0)
f(0), f(1), f(2) are computed multiple times!
Exponential time for finding f(n)!
Modification
Computing f(4)
f(4)
f(3)
f(2)
f(1)
f(2)
f(1)
f(1)
f(0)
f(0)
Dynamic Programming
Idea
Example 1 Tiling
Recurrence
Recurrence
Base Cases
When n = 0, f(n) = 1.
When n = 1, f(n) = 1.
Overlapping Subproblems
f(n 3) ways to fill
Implementation 1
Bottom-up approach:
int ways[251];
int main(){
ways[0] = 1;
ways[1] = 1;
for (int i = 2; i <= 250; ++i)
ways[i] = ways[i-1] +
2 * ways[i-2];
}
Implementation 2
Top-down approach:
int ways[251];
int f(int n){
if (ways[n] != -1) return ways[n];
return (ways[n] = f(n-1) + 2*f(n-2));
}
int main(){
ways[0] = 1;
ways[1] = 1;
for (int i = 2; i <= 250; ++i)
ways[i] = -1;
// cout << f(250) << \n;
}
Bottom-up
Important
No
Top-down
Not
important
Yes
Low
High
Possible
Never
Remarks
1 n 1
n
1
)
The number of solutions is
3
Available tiles: 21
Find the number of ways to completely
fill the board.
Let f(n) be the number of ways to fill a
board of size n3
What is the relationship between f(n)
and f(n1), f(n2), f(n3), ?
Example
Recurrence
g(n) is the number of ways to fill a board of size n3 with one square at
the corner filled
f(n) = 2 g(n1) + f(n2), f(0) = 1, f(1) = 0
Remarks
2
4
3
7
Attempt 1
Observations
f(i, j) = the min. cost of any path from the top to square (i, j)
E.g. f(1, 1) = 16 (green path)
7
4
16
5
Attempt 1 Problems
Attempt 2
Observation: The paths that ends at square (i, j) can be can be classified
into n groups:
(i, j)
Attempt 3
(i, j1)
(i, j)
Let L(i, j) = minimum cost to square (i, j) from the left or from
above, similarly for R(i, j)
L(i, j) = min { L(i-1, j), R(i-1, j), L(i, j-1) } + c(i, j)
R(i, j) = min { L(i-1, j), R(i-1, j), R(i, j+1) } + c(i, j)
Answer = min { L(n-1, 0), L(n-1, 1), , L(n-1, m-1),
R(n-1, 0), R(n-1, 1), , R(n-1, m-1) }
Fill in the base cases yourself!
Time complexity: O(mn)
Summary
Example 4 Make
Palindrome
Idea
Algorithm
Let S = ABCB
table[i][j]: min. # of insertions required to make S[i..j] a
palindrome.
table[i][j] = table[i+1][j-1] if S[i] = S[j]
min{ table[i+1][j]+1, table[i][j-1]+1 },
otherwise
j 1
table[1][4]
table[1][3]+1
table[1][4] =
table[2][4]+1
int table[1000][1000];
string S;
void backtrack(i, j){
if (i > j) return;
if (i == j) cout << S[i];
else if (S[i] == S[j]){
cout << S[i];
backtrack(i+1, j-1);
cout << S[j];
}
else if (table[i+1][j]+1 == table[i][j]){
cout << S[i];
backtrack(i+1, j);
cout << S[i];
}
else {
cout << S[j];
backtrack(i, j-1);
cout << S[j];
}
}
Remarks
S = ABAB
f(1, 2) is the same as f(3, 4), but they are
computed separately.
Store f(A), f(B), f(AB), f(BA), f(ABA),
f(BAB), f(ABAB) instead.
Example 5 Traveling
Salesman Problem
Traveling Salesman
Problem (TSP) (UVa
#10944)
Recurrence
f ({i}, i ) c(1, i )
f ( S , i ) min { f ( S {i}, j ) c( j , i )}
jS , j i
Answer = f(C, 1)
Time complexity: O(2n n2) (much better than
exhausting all (n-1)! possible circuits).
identify redundancy
define substructure (most difficult part)
formulate recurrence
Suggested Problems