Lectures 15-20: Dynamic Programming CSE 431/531: Analysis of Algorithms Lecturer: Shi Li

advertisement
CSE 431/531: Analysis of Algorithms
Lectures 15-20: Dynamic Programming
Lecturer: Shi Li
Department of Computer Science and Engineering
University at Buffalo
Spring 2016
MoWeFr 3:00-3:50pm
Knox 110
Different Paradigms for Designing Algorithms
Greedy algorithm
Make a greedy choice
Reduce the problem to a sub-problem and solve it iteratively
Divide-and-conquer
Break a problem into many independent sub-problems
Solve each sub-problem
Combine solutions for sub-problems to form a solution for the
original one
Dynamic programming
Break up a problem into many overlapping sub-problems
Build solutions for larger and larger sub-problems
Use a table to store solutions for sub-problems for reuse
Outline
1
Weighted Interval Scheduling
2
Subset Sum Problem
3
Knapsack Problem
4
Longest Common Subsequence
5
Longest Common Subsequence in Linear Space
6
Matrix Chain Multiplication
Recall: Interval Schduling
Input: n jobs, job i with start time si and finish time fi
each job has a weight (or value) vi > 0
i and j are compatible if [si , fi ) and [sj , fj ) are disjoint
Output: a maximum-size subset of mutually compatible jobs
0
2
1
3
4
100
5
6
50
9
30
25
50
90
80
8
7
80
70
Optimum value = 220
Hard to Design a Greedy Algorithm
Job
Job
Job
No,
0
with
with
with
with
the earliest finish time? No, we are ignoring weights
the largest weight? No, we are ignoring times
the largest weight/length?
uniform weights, we are choosing the shortest job
1
2
3
4
5
6
7
8
9
Designing a Dynamic Programming Algorithm
0
2
2
1
3
100
4
3
1
80
4
5
5
50
6
7
8
7
6
9
9 30
25
90
8
50
80
70
Sort jobs according to non-decreasing order of finish times
opt(i): optimal value for instance defined by jobs
{1, 2, · · · , i}
opt(0) = 0, opt(1) = 80, opt(2) = 100, opt(3) = 100
opt(4) = 105, opt(5) = 150, opt(6) = 170, opt(7) = 185
Designing a Dynamic Programming Algorithm
0
2
2
1
3
100
4
3
1
80
4
5
5
50
6
7
8
7
6
9
9 30
25
90
8
50
80
70
opt(i): optimal value for instance defined by jobs
{1, 2, · · · , i}
In the optimum solution for {1, 2, 3, · · · , i},
if job i is not selected, then opt(i) = opt(i − 1)
if job i is selected, then opt(i) = vi + opt(pi )
pi : the largest j such that fj ≤ si
opt(i) = max{opt(i − 1), vi + opt(pi )}
0
2
2
1
3
100
4
3
1
80
4
5
5
50
6
7
8
7
6
9
9 30
25
90
8
50
80
70
opt(i) = max{opt(i − 1), vi + opt(pi )}
opt(0) = 0
opt(1) = max{opt(0), 80 + opt(0)} = 80
opt(2) = max{opt(1), 100 + opt(0)} = 100
opt(3) = max{opt(2), 90 + opt(0)} = 100
opt(4) = max{opt(3), 25 + opt(1)} = 105
opt(5) = max{opt(4), 50 + opt(3)} = 150
0
2
2
1
3
100
4
3
1
80
4
5
5
50
6
7
8
7
6
9
9 30
25
90
8
50
80
70
opt(i) = max{opt(i − 1), vi + opt(pi )}
opt(0) = 0, opt(1) = 80, opt(2) = 100
opt(3) = 100, opt(4) = 105, opt(5) = 150
opt(6) = max{opt(5), 70 + opt(3)} = 170
opt(7) = max{opt(6), 80 + opt(4)} = 185
opt(8) = max{opt(7), 50 + opt(6)} = 220
opt(9) = max{opt(8), 30 + opt(7)} = 220
Recursive Algorithm
1
2
sort and compute p
return compute-opt(n)
compute-opt(i)
1
2
3
4
if i = 0 then
return 0
else
return max{compute-opt(i − 1), vi + compute-opt(pi )}
Running time can be exponential in n
Dynamic Programming
1
2
3
4
sort and compute p
opt[0] ← 0
for i ← 1 to n
opt[i] ← max{opt[i − 1], vi + opt[pi ]}
Bottleneck is sorting and computing p: O(n lg n).
Memoized Recursive Algorithm
1
2
3
sort and compute p
opt[0] ← 0 and opt[i] ← ∞ for every i = 1, 2, 3, · · · , n
return compute-opt(n)
compute-opt(i)
1
2
3
4
5
if opt[i] 6= ∞ then
return opt[i]
else
opt[i] ← max{compute-opt(i − 1), vi + compute-opt(pi )}
return opt[i]
Running time the same as dynamic programming: O(n lg n)
How Can We Recover the Optimum Schedule?
1
2
3
4
5
6
7
8
9
sort and compute p
opt[0] ← 0
for i ← 1 to n
if opt[i − 1] ≥ vi + opt[pi ]
opt[i] ← opt[i − 1]
b[i] ← N
else
opt[i] ← vi + opt[pi ]
b[i] ← Y
1
2
3
4
5
6
7
8
i ← n, S ← ∅
while i 6= 0
if b[i] = N
i←i−1
else
S ← S ∪ {i}
i ← pi
return S
Longest Path Problem in Node Weighted DAG
Input: a DAG (Directed Acyclic Graph) G = (V, E)
for every v ∈ V , a weight wv ∈ R≥0 ;
two special vertices s, t ∈ V
P
Output: the path P from s to t that maximizes v∈P wv
i.e., the total weight of nodes in the path
s
1
6
4
t
2
3
5
OPT=13
Reduction to Longest Path Problem
For every job i, there is a node i with weight vi .
For every two jobs i, j such that ti ≤ sj , there is an edge
(i, j)
Add source s and sink t with weight 0, and an edge from s
to every vertex, and add an edge from every vertex to t.
Compute longest path from s to t
Reduction to Longest Path Problem
s
0
0
2
2
1
3
100
4
3
1
80
4
5
5
50
6
7
8
7
6
9
80
100 2
1
90
3
9 30
25
90
8
edges to all vertices
80
50
4
25
50
5
6
70
70
7
80
8
9
50
t
30
0
edges from all vertices
Ideas of Dynamic Programming
Break up a problem into many overlapping sub-problems
Build solutions for larger and larger sub-problems
Use a table to store solutions for sub-problems for reuse
Outline
1
Weighted Interval Scheduling
2
Subset Sum Problem
3
Knapsack Problem
4
Longest Common Subsequence
5
Longest Common Subsequence in Linear Space
6
Matrix Chain Multiplication
Subset Sum Problem
Input: an integer bound W > 0
a set of n items, each with an integer weight wi > 0
Output: a subset S of items that
X
X
maximizes
wi
s.t.
wi ≤ W.
i∈S
i∈S
Motivation: you have budget W , and want to buy a subset
of items, so as to spend as much money as possible.
Example:
W = 35, n = 5, w = (14, 9, 17, 10, 13)
Optimum: S = {1, 2, 4} and 14 + 9 + 10 = 33
Greedy Algorithms for Subset Sum
Candidate Algorithm:
Sort according to non-increasing order of weights
Select items in the order as long as the total weight remains
below W
Q: Does candidate algorithm always produce optimal solutions?
A: No. W = 100, n = 3, w = (51, 50, 50).
Q: What if we change “non-increasing” to “non-decreasing”?
A: Still no. W = 100, n = 3, w = (1, 50, 50)
Design a Dynamic Programming Algorithm
Instance: n, W, (w1 , w2 , · · · , wn );
opt[n, W, (w1 , w2 , · · · , wn )]: the optimum value of instance
If we do not choose item n
residual instance: n − 1, W, (w1 , w2 , · · · , wn−1 )
value: opt[n − 1, W, (w1 , w2 , · · · , wn−1 )]
If we choose item n (assuming W ≥ wn )
residual instance: n − 1, W − wn , (w1 , w2 , · · · , wn−1 )
value: opt[n − 1, W − wn , (w1 , w2 , · · · , wn−1 )] + wn
No Need to Remember the w Vector
Fix (w1 , w2 , · · · , wn ). Initial instance: n, W .
opt[n, W ]: the optimum value of instance
If we do not choose item n
residual instance: n − 1, W
value: opt[n − 1, W ]
If we choose item n (assuming W ≥ wn )
residual instance: n − 1, W − wn
value: opt[n − 1, W − wn ] + wn
Dynamic Programming
for every i ∈ {0, 1, 2, 3, · · · , n}, W 0 ∈ {0, 1, 2, · · · , W }, let
opt[i, W 0 ] be the optimum value of the instance where we
have budget W 0 and items {1, 2, · · · , i}
If i = 0, then opt[i, W 0 ] = 0
If i > 0 and wi > W 0 , then
opt[i, W 0 ] = opt[i − 1, W 0 ].
If i > 0 and wi ≤ W 0 , then
0
opt[i, W ] = max
opt[i − 1, W 0 ]
.
opt[i − 1, W 0 − wi ] + wi
Dynamic Programming
1
2
3
4
5
6
7
8
for W 0 ← 0 to W
opt[0, W 0 ] ← 0
for i ← 1 to n
for W 0 ← 0 to W
opt[i, W 0 ] ← opt[i − 1, W 0 ]
if wi ≥ W 0 and opt[i − 1, W 0 − wi ] + wi ≥ opt[i, W 0 ]
then
opt[i, W 0 ] ← opt[i − 1, W 0 − wi ] + wi
return opt[n, W ]
Recover the Optimum Set
1
2
3
4
5
6
7
8
9
10
for W 0 ← 0 to W
opt[0, W 0 ] ← 0
for i ← 1 to n
for W 0 ← 0 to W
opt[i, W 0 ] ← opt[i − 1, W 0 ]
b[i, W 0 ] ← N
if wi ≥ W 0 and opt[i − 1, W 0 − wi ] + wi ≥ opt[i, W 0 ]
then
opt[i, W 0 ] ← opt[i − 1, W 0 − wi ] + wi
b[i, W 0 ] ← Y
return opt[n, W ]
Recover the Optimum Set
1
2
3
4
5
6
7
i ← n, W 0 ← W, S ← ∅
while i > 0
if b[i, W 0 ] = Y then
W 0 ← W 0 − wi
S ← S ∪ {i}
i←i−1
return S
Running Time of Algorithm
1
2
3
4
5
6
7
8
for W 0 ← 0 to W
opt[0, W 0 ] ← 0
for i ← 1 to n
for W 0 ← 0 to W
opt[i, W 0 ] ← opt[i − 1, W 0 ]
if wi ≥ W 0 and opt[i − 1, W 0 − wi ] + wi ≥ opt[i, W 0 ]
then
opt[i, W 0 ] ← opt[i − 1, W 0 − wi ] + wi
return opt[n, W ]
Running time is O(nW )
Running time is pseudo-polynomial because it depends on
value of the input integers.
Outline
1
Weighted Interval Scheduling
2
Subset Sum Problem
3
Knapsack Problem
4
Longest Common Subsequence
5
Longest Common Subsequence in Linear Space
6
Matrix Chain Multiplication
Knapsack Problem
Input: an integer bound W > 0
a set of n items, each with an integer weight wi > 0
a value vi > 0 for each item i
Output: a subset S of items that
X
X
maximizes
vi
s.t.
wi ≤ W.
i∈S
i∈S
Motivation: you have budget W , and want to buy a subset
of items, so as to spend as much money as possible.
Greedy Algorithm
1
sort items according to non-increasing order of vi /wi
2
for each item in the ordering
3
take the item if we have enough budget
Bad example: W = 100, n = 2, w = (1, 100), v = (1.1, 100).
Optimum takes item 2 and greedy takes item 1.
Indeed, greedy algorithm “almost” works, except for the last
item we missed
Fractional Knapsack Problem
Input: an integer bound W > 0,
a set of n items, each with an integer weight wi > 0
a value vi > 0 for each item i
Output: a vector (α1 , α2 , · · · , αn ) ∈ [0, 1]n
maximizes
n
X
i=1
αi vi
s.t.
n
X
i=1
αi wi ≤ W.
sort items according to non-increasing order of vi /wi ,
for each item according to the ordering, take as much fraction
of the item as possible.
Greedy is Optimum for Fractional Knapsack
sort items according to selecting the item with the largest
vi /wi ,
for each item according to the ordering, take as much fraction
of the item as possible.
W = 100, n = 2, w = (1, 100), v = (1.1, 100).
α1 = 1, α2 = 0.99, value = 1.1 + 99 = 100.1.
Idea of proof: exchanging argument.
DP for ({0, 1}-)Knapsack Problem
opt[i, W 0 ]: the optimum value when budget is W 0 and items
are {1, 2, 3, · · · , i}.
If i = 0, opt[i, W 0 ] = 0 for every W 0 = 0, 1, 2, · · · , W .
If i > 0 and wi > W 0 , then
opt[i, W 0 ] = opt[i − 1, W 0 ].
If i > 0 and wi ≤ W 0 , then
0
opt[i, W ] = max
opt[i − 1, W 0 ]
.
opt[i − 1, W 0 − wi ] + vi
Path-Structure Dynamic Programming
Weighted Interval Scheduling:
opt[i] = max{opt[i − 1], opt[pi ] + vi }
Knapsack Problem:
opt[i, W 0 ] = max{opt[i − 1, W 0 ], opt[i − 1, W 0 − wi ] + vi }
0
1
2
···
n−1
Cell in the table indexed by (i, C)
i: index of node in the path
C: additional information.
opt(i, C) depends on the values of opt(j, C 0 ) for j < i.
n
Exercise: Items with 3 Parameters
Input: integer bounds W > 0, S > 0,
a set of n items, each with an integer weight wi > 0
a size si > 0 for each item i
a value vi > 0 for each item i
Output: a subset S of items that
X
maximizes
vi
s.t.
i∈S
X
i∈S
wi ≤ W and
X
i∈S
si ≤ S
Exercise: Maximum-Weight Subsets with Gaps
Input: n, integers w1 , w2 , · · · , wn ≥ 0.
Output: a set S ⊆ {1, 2, 3 · · · , n} that
X
maximizes
wi
s.t.
i∈S
∀i, j ∈ S, i 6= j, we have |i − j| ≥ 2.
Example: n = 7, w = (10, 80, 100, 90, 30, 50, 70)
Choose item 2, 4, 7: value = 80 + 90 + 70 = 240
Exercise: Counting Number of Domino Coverings
Input: n
Output: number of ways to cover a n × 2 grid using domino
tiles
Example: 5 different ways if n = 4:
How about number of ways to cover a n × 3 grid?
Outline
1
Weighted Interval Scheduling
2
Subset Sum Problem
3
Knapsack Problem
4
Longest Common Subsequence
5
Longest Common Subsequence in Linear Space
6
Matrix Chain Multiplication
Subsequence
A = bacdca
C = adca
C is a subsequence of A
Def. Given two sequences A[1 .. n] and C[1 .. t] of letters, C is
called a subsequence of A if there exists integers
1 ≤ i1 < i2 < i3 < . . . < it ≤ n such that A[ij ] = C[j] for every
j = 1, 2, 3, · · · , t.
Exercise: how to check if sequence C is a subsequence of A?
Longest Common Subsequence
Input: A[1 .. n] and B[1 .. m]
Output: the longest common subsequence of A and B
Example:
A = bacdca
B = adbcda
LCS(A, B) = adca
Applications: edit distance (diff utility), similarity of DNAs
Matching View of LCS
b
a
c
d
c
a
a
d
b
c
d
a
Goal of LCS: find a maximum-size non-crossing matching
between letters in A and letters in B.
Reduce to Subproblems
A = bacdca
B = adbcda
either the last letter of A is not matched:
need to compute LCS(bacdc, adbc)
or the last letter of B is not matched:
need to compute LCS(bacd, adbcd)
Dynamic Programming for LCS
opt[i, j], 0 ≤ i ≤ n, 0 ≤ j ≤ m: length of longest common
sub-sequence of A[1 .. i] and B[1 .. j].
if i = 0 or j = 0, then opt[i, j] = 0.
if i > 0, j > 0, then

if A[i] = B[j]

opt[i −
( 1, j − 1] + 1
opt[i, j] =
opt[i − 1, j]

if A[i] 6= B[j]
 max
opt[i, j − 1]
Dynamic Programming for LCS
1
2
3
4
5
6
7
8
9
10
11
for j ← 0 to m do
opt[0, j] ← 0
for i ← 1 to n
opt[i, 0] ← 0
for j ← 1 to m
if A[i] = B[j]
opt[i, j] ← opt[i − 1, j − 1] + 1, π[i, j] ← “-”
elseif opt[i, j − 1] ≥ opt[i − 1, j]
opt[i, j] ← opt[i, j − 1], π[i, j] ←“←”
else
opt[i, j] ← opt[i − 1, j], π[i, j] ← “↑”
Example
A
B
0
1
2
3
4
5
6
0
0
0
0
0
0
0
0
⊥
⊥
⊥
⊥
⊥
⊥
⊥
1
0⊥
0←
11↑
1↑
1↑
1-
1
b
a
2 3
a c
d b
2
0⊥
0←
1←
1←
22↑
2↑
3
0⊥
11←
1←
2←
2←
2←
4 5 6
d c a
c d a
4
5
0⊥ 0⊥
1← 1←
1← 1←
2- 2←
2← 33- 3←
3↑ 3←
6
0⊥
1←
22←
3←
3←
4-
Example: Find Common Subsequence
A
B
0
1
2
3
4
5
6
0
0
0
0
0
0
0
0
⊥
⊥
⊥
⊥
⊥
⊥
⊥
1
0⊥
0←
11↑
1↑
1↑
1-
1
b
a
2 3
a c
d b
2
0⊥
0←
1←
1←
22↑
2↑
3
0⊥
11←
1←
2←
2←
2←
4 5 6
d c a
c d a
4
5
0⊥ 0⊥
1← 1←
1← 1←
2- 2←
2← 33- 3←
3↑ 3←
6
0⊥
1←
22←
3←
3←
4-
Find Common Subsequence
1
2
3
4
5
6
7
8
9
i ← n, j ← m, S ←“”
while i > 0 and j > 0
if π[i, j] =“-” then
S ← A[i] o
n S, i ← i − 1, j ← j − 1
else if π[i, j] =“↑”
i←i−1
else
j ←j−1
return S
Variants of Problem
Edit Distance with Insertions and Deletions
Input: a string A
each time we can delete a letter from A or insert a
letter to A
Output: minimum number of operations (insertions or
deletions) we need to change A to B?
Example:
A = ocurrance, B = occurrence
3 operations: insert ’c’, remove ’a’ and insert ’e’
Obs. #OPs = length(A) + length(B) - 2 · length(LCS(A, B))
Variants of Problem
Edit Distance with Insertions, Deletions and Replacing
Input: a string A,
each time we can delete a letter from A, insert a letter
to A or change a letter
Output: how many operations do we need to change A to B?
Example:
A = ocurrance, B = occurrence.
3 operations: insert ’c’, change ’a’ to ’e’
No tight connection to LCS
Edit Distance (with Replacing)
opt[i, j], 0 ≤ i ≤ n, 0 ≤ j ≤ m: edit distance between
A[1 .. i] and B[1 .. j].
if i = 0 then opt[i, j] = j; if j = 0 then opt[i, j] = i.
if i > 0, j > 0, then

− 1, j − 1]
if A[i] = B[j]

opt[i 



 opt[i − 1, j] + 1
opt[i, j] =

min
if A[i] 6= B[j]
opt[i, j − 1] + 1





opt[i − 1, j − 1] + 1
More General Version of Edit Distance
insertion or deletion costs δ
replacing a letter x with a letter y costs cx,y (assume
cx,x = 0)
if i = 0 then opt[i, j] = jδ; if j = 0 then opt[i, j] = iδ.
if i > 0, j > 0, then

opt[i − 1, j] + δ

opt[i, j − 1] + δ
opt[i, j] = min

opt[i − 1, j − 1] + cA[i],B[j]
Def. A palindrome is a string which reads the same backward or
forward.
example: “racecar”, “wasitacaroracatisaw”, ”putitup”
Longest Palindrome Subsequence
Input: a sequence A
Output: the longest subsequence C of A that is a palindrome.
Example:
Input: acbcedeacab
Output: acedeca
Longest Path Problem in Edge Weighted DAG
Input: a DAG (Directed Acyclic Graph) G = (V, E);
for every e ∈ E, a weight we ∈ R≥0 ;
two special vertices s, t ∈ V
P
Output: the path P from s to t that maximizes e∈P we , i.e.,
the total weight of edges in the path
6
1
s
2
3
5
4
6
t
OPT=13
LCS as Longest-Path: Example
b
a
c
d
c
a
s
A = bacdca
B = adbcda
0 for vertical and
horizontal edges
1 for diagonal edges
a
d
b
c
d
a
t
LCS as a Longest-Path Problem
for every i ∈ {0, 1, 2, · · · , n} and j ∈ {0, 1, 2, 3, · · · , m},
there is a vertex vi,j
for every i ∈ {0, 1, 2, · · · , n} and j ∈ {1, 2, 3, · · · , m}, there
is a horizontal edge of value 0 from vi,j−1 to vi,j
for every i ∈ {1, 2, · · · , n} and j ∈ {0, 1, 2, 3, · · · , m}, there
is a vertical edge of value 0 from vi−1,j to vi,j
for every i ∈ {1, 2, · · · , n} and j ∈ {1, 2, 3, · · · , m} such
that A[i] = B[j], there is a diagonal edge of value 1 from
vi−1,j−1 to vi,j
goal is to compute the longest path from v0,0 to vn,m
Outline
1
Weighted Interval Scheduling
2
Subset Sum Problem
3
Knapsack Problem
4
Longest Common Subsequence
5
Longest Common Subsequence in Linear Space
6
Matrix Chain Multiplication
Computing the Length of LCS
1
2
3
4
5
6
7
8
9
10
11
for j ← 0 to m do
opt[0, j] ← 0
for i ← 1 to n
opt[i, 0] ← 0
for j ← 1 to m
if A[i] = B[j]
opt[i, j] ← opt[i − 1, j − 1] + 1
elseif opt[i, j − 1] ≥ opt[i − 1, j]
opt[i, j] ← opt[i, j − 1]
else
opt[i, j] ← opt[i − 1, j]
Obs. The i-th row of table only depends on (i − 1)-th row.
Reducing Space to O(n + m)
Obs. The i-th row of table only depends on (i − 1)-th row.
Q: How to use this observation to reduce space?
A: We only keep two rows: the (i − 1)-th row and the i-th row.
Linear Space Algorithm to Compute Length of LCS
1
2
3
4
5
6
7
8
9
10
11
12
for j ← 0 to m do
opt[0, j] ← 0
for i ← 1 to n
opt[i mod 2, 0] ← 0
for j ← 1 to m
if A[i] = B[j]
opt[i mod 2, j] ← opt[i − 1 mod 2, j − 1] + 1
elseif opt[i mod 2, j − 1] ≥ opt[i − 1 mod 2, j]
opt[i mod 2, j] ← opt[i mod 2, j − 1]
else
opt[i mod 2, j] ← opt[i − 1 mod 2, j]
return opt[n mod 2, m]
Linear Space ALgorithm to Recover LCS
| · | denotes length of a sequence
Lemma There is a q ∈ {0, 1, · · · , m}, such that LCS(A, B)
equals
LCS(A[1..n/2], B[1..q]) + LCS(A[n/2 + 1..n], B[q + 1..m])
n/2 + 1
n/2
A
B
q
q+1
n/2 + 1
n/2
A
B
q
q+1
Q: How can we find such a q using linear space?
A: Use both forward and backward DP
Q: After we found such a q, what can we do?
A: Use divide-and-conquer to solve two sub problems
Backward Dynamic Programming for LCS
opt[i, j], 1 ≤ i ≤ n + 1, 1 ≤ j ≤ m + 1: length of longest
common sub-sequence of A[i .. n] and B[j .. m].
if i = n + 1 or j = m + 1, then opt[i, j] = 0.
if i ≤ n, j ≤ m, then

if A[i] = B[j]

opt[i +
( 1, j + 1] + 1
opt[i, j] =
opt[i + 1, j]

if A[i] 6= B[j]
 max
opt[i, j + 1]
Backward Dynamic Programming for LCS
1
2
3
4
5
6
7
8
9
10
11
12
for j ← 1 to m + 1 do
opt[n + 1 mod 2, j] ← 0
for i ← n downto 1
opt[i mod 2, n + 1] ← 0
for j ← m downto 1
if A[i] = B[j]
opt[i mod 2, j] ← opt[i + 1 mod 2, j + 1] + 1
elseif opt[i mod 2, j + 1] ≥ opt[i + 1 mod 2, j]
opt[i mod 2, j] ← opt[i mod 2, j + 1]
else
opt[i mod 2, j] ← opt[i + 1 mod 2, j]
return opt[1, m]
Q: How can we find such a q using linear space?
A: Use both forward and backward DP
opt: table used for forward DP
opt0 : table used for backward DP
forward DP: consider A[1..n/2] and B
backward DP: consider A[n/2 + 1..n] and B
find the q ∈ {0, 1, · · · , m} that maximizes
opt[n/2 mod 2, q] + opt0 [n/2 + 1 mod 2, q + 1]
Algorithm uses O(m) space
Q: How to use this observation to reduce space?
A: We only keep two rows: the (i − 1)-th row and the i-th row.
linear-space-LCS(A[1..n], B[1..m])
1
2
3
if n = 1 solve the problem directly and return
find q using O(m) space
return concatenation of linear-space-LCS(A[1..n/2], B[1..q])
and linear-space-LCS(A[n/2 + 1, n], B[q + 1, m])
we can reuse the space used for Statement 2
Space usage: O(n + m)
O(m + n) for storing input sequences and output sequence
O(m) for Statement 2
O(lg n) for storing the recursion tree
Analyze Running Time of Linear-Space-LCS
linear-space-LCS(A[1..n], B[1..m])
1
2
3
if n = 1 solve the problem directly and return
find q using O(m) space
return concatenation of linear-space-LCS(A[1..n/2], B[1..q])
and linear-space-LCS(A[n/2 + 1, n], B[q + 1, m])
Recurrence for running time:
T (n, m) ≤ cmn + T (n/2, q) + T (n/2, m − q)
To get intuition, let m = n and q = n/2:
T (n) ≤ 2T (n/2) + cn2 ⇒ T (n) = O(n2 )
T (n, m) ≤ cmn + T (n/2, q) + T (n/2, m − q)
Using substitution method to prove T (n, m) ≤ c0 nm:
T (n, m) ≤ cmn + T (n/2, q) + T (n/2, m − q)
≤ cmn + c0 (n/2)q + c0 (n/2)(m − q)
= cmn + c0 (n/2)m
= (c + c0 /2)nm = c0 nm
if c0 = 2c
Outline
1
Weighted Interval Scheduling
2
Subset Sum Problem
3
Knapsack Problem
4
Longest Common Subsequence
5
Longest Common Subsequence in Linear Space
6
Matrix Chain Multiplication
Matrix Chain Multiplication
Fact Multiplying two matrices of size r × k and k × c takes
r × k × c multiplications.
Matrix Chain Multiplication
Input: n matrices A1 , A2 , · · · , An of sizes
r1 × c1 , r2 × c2 , · · · , rn × cn , such that ci = ri+1 for
every i = 1, 2, · · · , n − 1.
Output: the order of computing A1 A2 · · · An with the minimum
number of multiplications
Example:
A1 : 10 × 100,
A2 : 100 × 5,
10 × 100
5 × 50
100 × 5
10 × 5
10 · 100 · 5
= 5000
10 × 50
10 · 5 · 50
= 2500
cost = 5000 + 2500 = 7500
A3 : 5 × 50
10 × 100
100 × 5
5 × 50
100 · 5 · 50
= 25000 100 × 50
10 · 100 · 50
= 50000
10 × 5
cost = 25000 + 50000 = 75000
(A1 A2 )A3 : 10 × 100 × 5 + 10 × 5 × 50 = 7500
A1 (A2 A3 ): 100 × 5 × 50 + 10 × 100 × 50 = 75000
Exercise: How many different ways are there to multiply n
matrics?
n = 4: there are 5 different ways
((A1 A2 )A3 )A4
(A1 (A2 A3 ))A4
(A1 A2 )(A3 A4 )
A1 ((A2 A3 )A4 )
A1 (A2 (A3 A4 ))
O(nc ) for some c, or cΩ(n) for some c?
exact answer: 2n−2
/n = (n − 1)-th Catalan number
n−1
1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786,
208012, 742900, 2674440, 9694845, 35357670, 129644790,
477638700, · · ·
Matrix Chain Multiplication: Design DP
Given A1 , A2 , · · · , An
Assume the last step is (A1 A2 · · · Ai )(Ai+1 Ai+2 · · · An )
Cost of last step: r1 × ci × cn
Optimality for sub-instances: we need to compute
A1 A2 · · · Ai and Ai+1 Ai+2 · · · An optimally
opt[i, j] : the minimum cost of computing Ai Ai+1 · · · Aj
for every i ∈ {1, 2, · · · , n}: opt[i, i] = 0
for every i, j such that 1 ≤ i < j ≤ n:
opt[i, j] = min (opt[i, k] + opt[k + 1, j] + ri ck cj )
k:i≤k<j
Matrix-Chain-Multiplication: DP
1
2
3
4
5
6
7
8
9
let opt[i, i] ← 0 for every i = 1, 2, · · · , n
for l ← 2 to n
for i ← 1 to n − l + 1
j ←i+l−1
opt[i, j] ← ∞
for k ← i to j − 1
if opt[i, k] + opt[k + 1, j] + ri ck cj < opt[i, j]
opt[i, j] ← opt[i, k] + opt[k + 1, j] + ri ck cj
return opt[1, n]
matrix
A1
size
30 × 35
1
2
3
4
5
6
A2
35 × 15
A3
15 × 5
A4
5 × 10
A5
10 × 20
A6
20 × 25
1
2
3
4
5
6
0 15750 7875 9375 11875 15125
⊥
0
2625 4375 7125 10500
⊥
⊥
0
750 2500 5375
⊥
⊥
⊥
0
1000 3500
⊥
⊥
⊥
⊥
0
5000
⊥
⊥
⊥
⊥
⊥
0
opt[3, 6] = minimum of
opt[3, 3] + f [4, 6] + r3 c3 c6 =
0 + 3500 + 15 × 5 × 25 = 5375
opt[3, 4] + f [5, 6] + r3 c4 c6 = 750 + 5000 + 15 × 10 × 25 = 9500
opt[3, 5] + f [6, 6] + r3 c5 c6 = 2500 + 0 + 15 × 20 × 25 =10000
Recover the Optimum Way of Multiplication
1
2
3
4
5
6
7
8
9
10
let opt[i, i] ← 0 for every i = 1, 2, · · · , n
for l ← 2 to n
for i ← 1 to n − l + 1
j ←i+l−1
opt[i, j] ← ∞
for k ← i to j − 1
opt[i, k] + opt[k + 1, j] + ri ck cj < opt[i, j]
opt[i, j] ← opt[i, k] + opt[k + 1, j] + ri ck cj
alertπ[i, j] ← k
return opt[1, n]
Constructing Optimal Solution
Print-Optimal-Order(i, j)
1
2
3
4
5
6
7
if i = j
print(“A”i )
else
print(“(”)
Print-Optimal-Order(i, π[i, j])
Print-Optimal-Order(π[i, j] + 1, j)
print(“)”)
Similar Problem: Optimum Binary Search Tree
n elements e1 < e2 < e3 < · · · < en
ei has frequency fi
goal: build a binary search tree for {e1 , e2 , · · · , en } with the
minimum accessing cost:
n
X
i=1
fi × (depth of ei in the tree)
Optimum Binary Search Tree
Example: f1 = 10, f2 = 5, f3 = 3
e1
e2
e2
e1
e3
10 × 1 + 5 × 2 + 3 × 3 = 29
10 × 2 + 5 × 1 + 3 × 2 = 31
10 × 3 + 5 × 2 + 3 × 1 = 43
e3
e3
e2
e1
suppose we decided to let ei be the root
e1 , e2 , · · · , ei−1 are on left sub-tree
ei+1 , ei+2 , · · · , en are on right sub-tree
dj : depth of ej in our tree
C, CL , CR : cost of tree, left sub-tree and right sub-tree
respectively
C=
n
X
f j dj =
j=1
=
=
n
X
j=1
n
X
j=1
n
X
fj +
j=1
fj +
i−1
X
j=1
n
X
j=1
fj (dj − 1)
fj (dj − 1) +
fj + CL + CR
n
X
j=i+1
fj (dj − 1)
C=
n
X
fj + CL + C R
j=1
In order to minimize C, need to minimize CL and CR
respectively
opti,j : the optimum cost for the instance (fi , fi+1 , · · · , fj )
for every i ∈ {1, 2, · · · , n, n + 1}: opt[i, i − 1] = 0
for every i, j such that 1 ≤ i ≤ j ≤ n,
opt[i, j] =
j
X
k=i
fk + min
k:i≤k≤j
opt[i, k − 1] + opt[k + 1, j]
Download