Lecture9_IO_BLG336E_2022
Lecture9_IO_BLG336E_2022
Analysis of Algorithms II
Lecture 9:
Dynamic Programming II
DNA Sequencing, Knapsack Problem
1
Last time
DNA: DNA:
AGCCCTAAGGGCTACCTAGCTT GACAGCCTACAAGCGTTAGCTTG
Longest Common Subsequence
• How similar are these two species?
DNA: DNA:
AGCCCTAAGGGCTACCTAGCTT GACAGCCTACAAGCGTTAGCTTG
• Pretty similar, their DNA has a long common subsequence:
AGCCTAAGCTTAGCTT
Longest Common Subsequence
• Subsequence:
• BDFH is a subsequence of ABCDEFGH
• If X and Y are sequences, a common subsequence
is a sequence which is a subsequence of both.
• BDFH is a common subsequence of ABCDEFGH and of
ABDFGHI
• A longest common subsequence…
• …is a common subsequence that is longest.
• The longest common subsequence of ABCDEFGH and
ABDFGHI is ABDFGH.
We sometimes want to find these
• Applications in bioinformatics
X A C G G T
Y A C G C T T A
Xi A C G G A
j
Yj A C G C T T A
Yj A C G C T T A
Case 0
0 if 𝑖 = 0 or 𝑗 = 0
• 𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
Case 1 Case 2
A C G G A A C G G T
Xi Xi
Yj A C G C T T A Yj A C G C T T A
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the length
of the longest common subsequence.
• Step 3: Use dynamic programming to find the
length of the longest common subsequence.
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual LCS.
• Step 5: If needed, code this up like a reasonable
person.
LCS DP OMG BBQ
• LCS(X, Y):
• C[i,0] = C[0,j] = 0 for all i = 1,…,m, j=1,…n.
• For i = 1,…,m and j = 1,…,n:
• If X[i] = Y[j]:
• C[i,j] = C[i-1,j-1] + 1
• Else:
• C[i,j] = max{ C[i,j-1], C[i-1,j] }
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞ 𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
X A C G G A
Example
Y A C T G
Y
A C T G
0 0 0 0 0
A 0
C 0
X G 0
G 0
A 0
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
X A C G G A
Example
Y A C T G
Y
A C T G
0 0 0 0 0
A 0 1 1 1 1 So the LCM of X
C 0 1 2 2 2 and Y has length 3.
X G 0 1 2 2 3
G 0 1 2 2 3
A 0 1 2 2 3
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the length
of the longest common subsequence.
• Step 3: Use dynamic programming to find the
length of the longest common subsequence.
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual LCS.
• Step 5: If needed, code this up like a reasonable
person.
X A C G G A
Example
Y A C T G
Y
A C T G
0 0 0 0 0
A 0
C 0
X G 0
G 0
A 0
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
X A C G G A
Example
Y A C T G
Y
A C T G
0 0 0 0 0
A 0 1 1 1 1
C 0 1 2 2 2
X G 0 1 2 2 3
G 0 1 2 2 3
A 0 1 2 2 3
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
X A C G G A
Example
Y A C T G
Y
A C T G
• Once we’ve filled this in,
we can work backwards.
0 0 0 0 0
A 0 1 1 1 1
C 0 1 2 2 2
X G 0 1 2 2 3
G 0 1 2 2 3
A 0 1 2 2 3
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
X A C G G A
Example
Y A C T G
Y
A C T G
• Once we’ve filled this in,
we can work backwards.
0 0 0 0 0
A 0 1 1 1 1
C 0 1 2 2 2
X G 0 1 2 2 3
Example
Y A C T G
Y
A C T G
• Once we’ve filled this in,
we can work backwards.
0 0 0 0 0 • A diagonal jump means
that we found an element
A 0 1 1 1 1
of the LCS!
C 0 1 2 2 2
A 0 1 2 2 3
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
X A C G G A
Example
Y A C T G
Y
A C T G
• Once we’ve filled this in,
we can work backwards.
0 0 0 0 0 • A diagonal jump means
that we found an element
A 0 1 1 1 1
of the LCS!
C 0 1 2 2 2 That 2 may as well
have come from
X G 0 1 2 2 3
this other 2. G
G 0 1 2 2 3
A 0 1 2 2 3
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
X A C G G A
Example
Y A C T G
Y
A C T G
• Once we’ve filled this in,
we can work backwards.
0 0 0 0 0 • A diagonal jump means
that we found an element
A 0 1 1 1 1
of the LCS!
C 0 1 2 2 2
X G 0 1 2 2 3 G
G 0 1 2 2 3
A 0 1 2 2 3
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
X A C G G A
Example
Y A C T G
Y
A C T G
• Once we’ve filled this in,
we can work backwards.
0 0 0 0 0 • A diagonal jump means
that we found an element
A 0 1 1 1 1
of the LCS!
C 0 1 2 2 2
X G 0 1 2 2 3 C G
G 0 1 2 2 3
A 0 1 2 2 3
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
X A C G G A
Example
Y A C T G
Y
A C T G
• Once we’ve filled this in,
we can work backwards.
0 0 0 0 0 • A diagonal jump means
that we found an element
A 0 1 1 1 1
of the LCS!
C 0 1 2 2 2
X G 0 1 2 2 3 A C G
G 0 1 2 2 3
This is the LCS!
A 0 1 2 2 3
0 if 𝑖 = 0 or 𝑗 = 0
𝐶 𝑖, 𝑗 = ൞𝐶 𝑖 − 1, 𝑗 − 1 + 1 if 𝑋 𝑖 = 𝑌 𝑗 and 𝑖, 𝑗 > 0
max 𝐶 𝑖, 𝑗 − 1 , 𝐶 𝑖 − 1, 𝑗 if 𝑋 𝑖 ≠ 𝑌 𝑗 and 𝑖, 𝑗 > 0
This gives an algorithm to recover the actual LCS
not just its length
Item:
Weight: 6 2 4 3 11
Value:
20 8 14 13 35
• Unbounded Knapsack:
• Suppose I have infinite copies of all of the items.
• What’s the most valuable way to fill the knapsack?
Total weight: 10
Total value: 42
• 0/1 Knapsack:
• Suppose I have only one copy of each item.
• What’s the most valuable way to fill the knapsack?
Total weight: 9
Total value: 35
Some notation
Item:
Weight: w1 w2 w3 … wn
Value: v1 v2 v3 vn
Capacity: W
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the value of
the optimal solution.
• Step 3: Use dynamic programming to find the value
of the optimal solution.
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual solution.
• Step 5: If needed, code this up like a reasonable
person.
Optimal substructure
• Sub-problems:
• Unbounded Knapsack with a smaller knapsack.
Weight wi
Value vi
Capacity x
• Then this optimal for capacity x - wi: Value V
K[x] = maxi { + }
The maximum is over Optimal way to The value of
all i so that 𝑤𝑖 ≤ 𝑥. fill the smaller item i.
knapsack
• Open problem!
• (But probably the answer is no…otherwise P = NP)
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the value of
the optimal solution.
• Step 3: Use dynamic programming to find the value
of the optimal solution.
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual solution.
• Step 5: If needed, code this up like a reasonable
person.
Let’s write a bottom-up DP algorithm
• UnboundedKnapsack(W, n, weights, values):
• K[0] = 0
• for x = 1, …, W:
• K[x] = 0
• for i = 1, …, n:
• if 𝑤𝑖 ≤ 𝑥:
• 𝐾 𝑥 = max{ 𝐾 𝑥 , 𝐾 𝑥 − 𝑤𝑖 + 𝑣𝑖 }
• return K[W]
K[x] = maxi { + }
K[x] = maxi { + }
Item:
Weight: 1 2 3
Value: 1 4 6
Capacity: 4
• UnboundedKnapsack(W, n, weights, values):
• K[0] = 0
• ITEMS[0] = ∅
Example • for x = 1, …, W:
• K[x] = 0
• for i = 1, …, n:
0 1 2 3 4 • if 𝑤𝑖 ≤ 𝑥:
• 𝐾 𝑥 = max{ 𝐾 𝑥 , 𝐾 𝑥 − 𝑤𝑖 + 𝑣𝑖 }
• If K[x] was updated:
K 0 1 • ITEMS[x] = ITEMS[x – wi] ∪ { item
• return ITEMS[W]
ITEMS
Item:
Weight: 1 2 3
Value: 1 4 6
ITEMS[1] = ITEMS[0] +
Capacity: 4
• UnboundedKnapsack(W, n, weights, values):
• K[0] = 0
• ITEMS[0] = ∅
Example • for x = 1, …, W:
• K[x] = 0
• for i = 1, …, n:
0 1 2 3 4 • if 𝑤𝑖 ≤ 𝑥:
• 𝐾 𝑥 = max{ 𝐾 𝑥 , 𝐾 𝑥 − 𝑤𝑖 + 𝑣𝑖 }
• If K[x] was updated:
K 0 1 2 • ITEMS[x] = ITEMS[x – wi] ∪ { item
• return ITEMS[W]
ITEMS
Item:
Weight: 1 2 3
Value: 1 4 6
ITEMS[2] = ITEMS[1] +
Capacity: 4
• UnboundedKnapsack(W, n, weights, values):
• K[0] = 0
• ITEMS[0] = ∅
Example • for x = 1, …, W:
• K[x] = 0
• for i = 1, …, n:
0 1 2 3 4 • if 𝑤𝑖 ≤ 𝑥:
• 𝐾 𝑥 = max{ 𝐾 𝑥 , 𝐾 𝑥 − 𝑤𝑖 + 𝑣𝑖 }
• If K[x] was updated:
K 0 1 4 • ITEMS[x] = ITEMS[x – wi] ∪ { item
• return ITEMS[W]
ITEMS
Item:
Weight: 1 2 3
Value: 1 4 6
ITEMS[2] = ITEMS[0] +
Capacity: 4
• UnboundedKnapsack(W, n, weights, values):
• K[0] = 0
• ITEMS[0] = ∅
Example • for x = 1, …, W:
• K[x] = 0
• for i = 1, …, n:
0 1 2 3 4 • if 𝑤𝑖 ≤ 𝑥:
• 𝐾 𝑥 = max{ 𝐾 𝑥 , 𝐾 𝑥 − 𝑤𝑖 + 𝑣𝑖 }
• If K[x] was updated:
K 0 1 4 5 • ITEMS[x] = ITEMS[x – wi] ∪ { item
• return ITEMS[W]
ITEMS
Item:
Weight: 1 2 3
Value: 1 4 6
ITEMS[3] = ITEMS[2] +
Capacity: 4
• UnboundedKnapsack(W, n, weights, values):
• K[0] = 0
• ITEMS[0] = ∅
Example • for x = 1, …, W:
• K[x] = 0
• for i = 1, …, n:
0 1 2 3 4 • if 𝑤𝑖 ≤ 𝑥:
• 𝐾 𝑥 = max{ 𝐾 𝑥 , 𝐾 𝑥 − 𝑤𝑖 + 𝑣𝑖 }
• If K[x] was updated:
K 0 1 4 6 • ITEMS[x] = ITEMS[x – wi] ∪ { item
• return ITEMS[W]
ITEMS
Item:
Weight: 1 2 3
Value: 1 4 6
ITEMS[3] = ITEMS[0] +
Capacity: 4
• UnboundedKnapsack(W, n, weights, values):
• K[0] = 0
• ITEMS[0] = ∅
Example • for x = 1, …, W:
• K[x] = 0
• for i = 1, …, n:
0 1 2 3 4 • if 𝑤𝑖 ≤ 𝑥:
• 𝐾 𝑥 = max{ 𝐾 𝑥 , 𝐾 𝑥 − 𝑤𝑖 + 𝑣𝑖 }
• If K[x] was updated:
K 0 1 4 6 7 • ITEMS[x] = ITEMS[x – wi] ∪ { item
• return ITEMS[W]
ITEMS
Item:
Weight: 1 2 3
Value: 1 4 6
ITEMS[4] = ITEMS[3] +
Capacity: 4
• UnboundedKnapsack(W, n, weights, values):
• K[0] = 0
• ITEMS[0] = ∅
Example • for x = 1, …, W:
• K[x] = 0
• for i = 1, …, n:
0 1 2 3 4 • if 𝑤𝑖 ≤ 𝑥:
• 𝐾 𝑥 = max{ 𝐾 𝑥 , 𝐾 𝑥 − 𝑤𝑖 + 𝑣𝑖 }
• If K[x] was updated:
K 0 1 4 6 8 • ITEMS[x] = ITEMS[x – wi] ∪ { item
• return ITEMS[W]
ITEMS
Item:
Weight: 1 2 3
Value: 1 4 6
ITEMS[4] = ITEMS[2] +
Capacity: 4
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the value of
the optimal solution.
• Step 3: Use dynamic programming to find the value
of the optimal solution.
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual solution.
• Step 5: If needed, code this up like a reasonable
person.
What have we learned?
• We can solve unbounded knapsack in time O(nW).
• If there are n items and our knapsack has capacity W.
• Unbounded Knapsack:
• Suppose I have infinite copies of all of the items.
• What’s the most valuable way to fill the knapsack?
Total weight: 10
Total value: 42
• 0/1 Knapsack:
• Suppose I have only one copy of each item.
• What’s the most valuable way to fill the knapsack?
Total weight: 9
Total value: 35
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the value of
the optimal solution.
• Step 3: Use dynamic programming to find the value
of the optimal solution.
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual solution.
• Step 5: If needed, code this up like a reasonable
person.
Optimal substructure: try 1
• Sub-problems:
• Unbounded Knapsack with a smaller knapsack.
I can’t use
any turtles…
Optimal substructure: try 2
• Sub-problems:
• 0/1 Knapsack with fewer items.
Then yet
more
items
Our sub-problems:
• Indexed by x and j
Capacity x
Value V
First j items Use only the first j items
Capacity x
Value V
First j-1 items Use only the first j-1 items.
Two cases item j
Weight wj
Value vj Capacity x
Value V
First j items Use only the first j items
• Then this is an optimal solution for j-1 items and a
smaller knapsack:
Capacity x – wi
Value V – vi
First j-1 items Use only the first j-1 items.
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the value of
the optimal solution.
• Step 3: Use dynamic programming to find the value
of the optimal solution.
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual solution.
• Step 5: If needed, code this up like a reasonable
person.
Recursive relationship
• Let K[x,j] be the optimal value for:
• capacity x,
• with j items.
0
j=1
0
j=2
0
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 0
j=1
0
j=2
0
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1
j=1
0
j=2
0
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1
j=1
0 1
j=2
0
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1
j=1
0 1
j=2
0 1
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 0
j=1
0 1
j=2
0 1
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1
j=1
0 1
j=2
0 1
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1
j=1
0 1 1
j=2
0 1
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1
j=1
0 1 4
j=2
0 1
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1
j=1
0 1 4
j=2
0 1 4
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1 0
j=1
0 1 4
j=2
0 1 4
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1 1
j=1
0 1 4
j=2
0 1 4
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1 1
j=1
0 1 4 1
j=2
0 1 4
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1 1
j=1
0 1 4 5
j=2
0 1 4
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1 1
j=1
0 1 4 5
j=2
0 1 4 5
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1 1
j=1
0 1 4 5
j=2
0 1 4 6
j=3
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
• Zero-One-Knapsack(W, n, w, v):
• K[x,0] = 0 for all x = 0,…,W
• K[0,i] = 0 for all i = 0,…,n
• for x = 1,…,W:
Example • for j = 1,…,n:
• K[x,j] = K[x, j-1]
• if wj ≤ x:
x=0 x=1 x=2 x=3 • K[x,j] = max{ K[x,j],
K[x – wj, j-1] + vj }
0 0 0 0 • return K[W,n]
j=0
0 1 1 1
j=1
0 1 4 5
j=2
So the optimal solution is to
0 1 4 6 put one watermelon in your
j=3 knapsack!
Item:
current relevant Weight: 1 2 3
entry previous entry Value: 1 4 6 Capacity: 3
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the value of
the optimal solution.
• Step 3: Use dynamic programming to find the value
of the optimal solution.
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual solution.
• Step 5: If needed, code this up like a reasonable
person.
What have we learned?
• We can solve 0/1 knapsack in time O(nW).
• If there are n items and our knapsack has capacity W.
vs.
In 0/1 knapsack, we
can only use each item
once, so it makes sense
to leave out one item
at a time.
1
2
An independent set 3
is a set of vertices • Given a graph with
so that no pair has weights on the
an edge between vertices…
them.
5 • What is the
1 independent set with
the largest weight?
Actually this problem is NP-complete.
So we are unlikely to find an efficient algorithm
• But if we also assume that the graph is a tree…
2 3
3 5
A tree is a
connected
2 3 1 graph with no
cycles.
5
2 5
Problem:
find a maximal independent set in a tree (with vertex weights).
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the value of
the optimal solution
• Step 3: Use dynamic programming to find the value
of the optimal solution
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual solution.
• Step 5: If needed, code this up like a reasonable
person.
Optimal substructure
• Subtrees are a natural candidate.
• There are two cases:
1. The root of this tree is in a not in
a maximal independent set.
2. Or it is.
Case 1:
the root is not in an maximal independent set
• Use the optimal solution
from these smaller problems.
Case 2:
the root is in an maximal independent set
• Then its children can’t be.
• Below that, use the optimal
solution from these smaller
subproblems.
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the value of
the optimal solution.
• Step 3: Use dynamic programming to find the value
of the optimal solution
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual solution.
• Step 5: If needed, code this up like a reasonable
person.
Recursive formulation: try 1
• Let A[u] be the weight of a maximal independent set
in the tree rooted at u.
•𝐴𝑢 =
σ𝑣∈𝑢.children 𝐴[𝑣]
max ൞
weight 𝑢 + σ𝑣∈𝑢.grandchildren 𝐴[𝑣]
σ𝑣∈𝑢.children 𝐴[𝑣]
• 𝐴 𝑢 = max ൞
weight 𝑢 + σ𝑣∈𝑢.children 𝐵[𝑣]
Recipe for applying Dynamic Programming
• Step 1: Identify optimal substructure.
• Step 2: Find a recursive formulation for the value of
the optimal solution.
• Step 3: Use dynamic programming to find the value
of the optimal solution.
• Step 4: If needed, keep track of some additional
info so that the algorithm from Step 3 can find the
actual solution.
• Step 5: If needed, code this up like a reasonable
person.
A top-down DP algorithm
• MIS_subtree(u):
• if u is a leaf:
• A[u] = weight(u)
• B[u] = 0
• else:
• for v in u.children:
• MIS_subtree(v)
• 𝐴 𝑢 = max{ σ𝑣∈𝑢.children 𝐴[𝑣] , weight 𝑢 + σ𝑣∈𝑢.children 𝐵[𝑣] }
• B 𝑢 = σ𝑣∈𝑢.children 𝐴[𝑣]
Running time?
• MIS(T): • We visit each vertex once, and at
every vertex we do O(1) work:
• MIS_subtree(T.root) • Make a recursive call
• return A[T.root] • look stuff up in tables
• Running time is O(|V|)
Why is this different from divide-and-conquer?
That’s always worked for us with tree problems before…
• MIS_subtree(u):
• if u is a leaf:
• return weight(u)
• else:
• for v in u.children:
• MIS_subtree(v)
• return max{ σ𝑣∈𝑢.children MIS_subtree(𝑣) ,
• MIS(T):
• return MIS_subtree(T.root)
Why is this different from divide-and-conquer?
That’s always worked for us with tree problems before…
SECTION 6.4
Knapsack problem
i vi wi
1 $1 1 kg
2 $6 2 kg
3 $18 5 kg
4 $22 6 kg
5 $28 7 kg
knapsackinstance
Creative Commons Attribution-Share Alike 2.5
(weightlimit W= 1 1 )
by Dake
32
Dynamic programming: quiz 3
Whichsubproblems?
33
Dynamic programming: two variables
3
4
Knapsack problem: bottom-up dynamic programming
FOR w = 0 TO W
M[0, w] 0.
3
6
Knapsack Problem
•Item 1: $5 (3t)
•Item 2: $7 (4t)
•Item 3: $8 (5t)
Knapsack Problem
Output function f(i,w)
Optimum output of a combination of items 1
to i with a cumulated weight of w or less.
f(i,w)
•Item 1: x1=$5 ; w1=3t
i •Item 2: x2=$7 ; w2=4t
•Item 3: x3=$8 ; w3=5t
•Item 1: x1=$5 ; w1=3t
•Item 2: x2=$7 ; w2=4t
•Item 3: x3=$8 ; w3=5t
Knapsack Problem
Table
1 2 3 4 5 6 7 8 9 10 W
1 Using only item 1
2
3
i
•Item 1: x1=$5 ; w1=3t
•Item 2: x2=$7 ; w2=4t
•Item 3: x3=$8 ; w3=5t
Knapsack Problem
Table
1 2 3 4 5 6 7 8 9 10 W
1
2 Using only item 1 & 2
3
i
•Item 1: x1=$5 ; w1=3t
•Item 2: x2=$7 ; w2=4t
•Item 3: x3=$8 ; w3=5t
Knapsack Problem
Table
1 2 3 4 5 6 7 8 9 10 W
1
2
3 Using items 1, 2 & 3
i
•Item 1: x1=$5 ; w1=3t
•Item 2: x2=$7 ; w2=4t
•Item 3: x3=$8 ; w3=5t
Knapsack Problem
Table
1 2 3 4 5 6 7 8 9 10 W
1 0 0 5 5 5 10
2
3
2 items n°1
0 items n°1 1 items n°1
2 w1 = 6
w1 = 3
•Item 1: x1=$5 ; w1=3t
•Item 2: x2=$7 ; w2=4t
•Item 3: x3=$8 ; w3=5t
Knapsack Problem
Table
1 2 3 4 5 6 7 8 9 10 w – w2 =
5–4=1
1 0 0 5 5 5 10 10 10 15 15
2 0 0 5 7
3
+ x2 (= 7)
COMPLETED TABLE
1 2 3 4 5 6 7 8 9 10
1 0 0 5 5 5 10 10 10 15 15
2 0 0 5 7 7 10 12 14 15 17
3 0 0 5 7 8 10 12 14 15 17
•Item 1: x1=$5 ; w1=3t
•Item 2: x2=$7 ; w2=4t
•Item 3: x3=$8 ; w3=5t
Knapsack Problem
Path
1 2 3 4 5 6 7 8 9 10
1 0 0 5 5 5 10 10 10 15 15
2 0 0 5 7 7 10 12 14 15 17
3 0 0 5 7 8 10 12 14 15 17
Remarks.
・Algorithm depends critically on assumption that weights are integral.
3
7
for w = 0 to W
M[0, w] = 0
for i = 1 to n
for w = 1 to W
if (wi > w)
M[i, w] = M[i-1, w]
else
M[i, w] = max {M[i-1, w], vi + M[i-1, w-wi ]}
return M[n, W]
131
Knapsack Algorithm
W+1
0 1 2 3 4 5 6 7 8 9 10 11
0 0 0 0 0 0 0 0 0 0 0 0
{1} 0 1 1 1 1 1 1 1 1 1 1 1
n+1 { 1, 2 } 0 1 6 7 7 7 7 7 7 7 7 7
{ 1, 2, 3 } 0 1 6 7 7 18 19 24 25 25 25 25
{ 1, 2, 3, 4 } 0 1 6 7 7 18 22 24 28 29 29 40
{ 1, 2, 3, 4, 5 } 0 1 6 7 7 18 22 28 29 34 34 40
D. Unknown.
equivalent to P≠ NPconjecture
because knapsack problem is NP-hard
38
COIN CHANGING
39
6. DYNAMIC PROGRAMMING I
SECTION 6.5
RNA secondary structure
C A
A A
A U G C
base
C G U A A G
G
U A U U A
base pair G
A C G C U
G
C G C G A G C
G
A U
RNAsecondarystructure forGUCGAUUGAGCGAAUGUAACAACGUGGCUACGGCGAGA
42
RNA secondary structure
G G
C U
C G 4
A C G U 3G G C C A U
U A
B =ACGUGGCCCAU
S = { (b1, b10), (b2, b9), (b3, b8) }
RNA secondary structure
G G
C G
4
4
A U G G G G C A U
A U
B =AUGGGGCAU
S = { (b1, b10), (b2, b9), (b3, b8) }
RNA secondary structure
・[Non-crossing] If (bi, bj) and (bk, bℓ) are two pairs in S, then we cannot
have i < k < j < ℓ.
G G
C U
C U 4
5
A G
A G U U G G C C A U
・[Non-crossing] If (bi, bj) and (bk, bℓ) are two pairs in S, then we cannot
have i < k < j < ℓ.
G G
C U
C G 4
6
A U
A U G U G G C C A U
・[Non-crossing] If (bi, bj) and (bk, bℓ) are two pairs in S, then we cannot
have i < k < j < ℓ.
A. Yes.
G C
C G U A A G
A U U A
G
G C U
G
C G A G C
A U
G 48
Dynamic programming: quiz 6
Which subproblems?
A. OPT(j) = max number of base pairs in secondary structure
of the substring b1b2 … bj.
C. Either A or B.
D. Neither A nor B.
49
RN A secondary structure: subproblems
Goal. OPT(n).
matchbases bt andbn
Choice. Match bases bt and bj.
1 t j last base
50
Dynamic programming over intervals
Case 1. If i ≥ j – 4.
・OPT(i, j ) = 0 by no-sharp-turns condition.
i t j 51
Dynamic programming: quiz 7
52
Bottom-up dynamic programming over intervals
RNA-SECONDARY-STRUCTURE(n, b1, …, bn ) j
6 7 8 9 10
FOR k = 5 TO n – 1 4 0 0 0
all needed values
FOR i = 1 TO n – k are already computed 3 0 0
i
j i + k. 2 0
• Min-cut
• Karger’s Algorithm
149