DAA Lec 8 Dynamic Programming (1)
DAA Lec 8 Dynamic Programming (1)
Email: [email protected]
Cell#: 0321-8956305
DESIGN & ANALYSIS OF ALGORITHMS
FALL 2024
Trade Space for Time
Categorize the Dynamic Programming
Knapsack Problem
Examples
Memoization
Writes down "1+1+1+1+1+1+1+1 =" on a
sheet of paper. "What's that equal to?"
Counting "Eight!"
Writes down another
"1+" on the left. "What
about that?"
"Nine!" " How'd you know it was
nine so fast?" "You just added
one more!"
"So you didn't need to recount because you
remembered there were
eight! Dynamic Programming is just a fancy way to say
remembering stuff to save time later!"
The intuition behind dynamic programming is that we trade space for
time, i.e. to say that instead of calculating all the states taking a lot of
time but no space, we take up space to store the results of all the sub-
problems to save time later.
Let's try to understand this by taking an example of Fibonacci
numbers.
Fibonacci (n)=1; if n=0
Fibonacci (n)=0; if n=1
Fibonacci (n)= Fibonacci(n-1)+Fibonacci (n-2)
So, the first few numbers in this series will be: 1, 1, 2, 3, 5, 8, 13, 21...
and so on!
1. Optimization problems.
2. Combinatorial problems.
1. Tabulation (Bottom-up)
solving all related sub-problems first, typically by filling up an n-dimensional table
2. Memoization (top-down)
maintaining a map of already solved sub problems, solve the "top" problem first which
typically recurses down to solve the sub-problems
These two approaches yield algorithms with the same asymptotic running time but
first approach has much better constant factors.
Given some items, pack the knapsack to get the maximum total
value. Each item has some weight and some value. Total weight
that we can carry is no more than some fixed number W.
So we must consider weights of items as well as their values.
Defining a Subproblem
If items are labeled 1..n, then a subproblem would be to find an optimal solution
for Sk = {items labeled
1, 2, .. k}
This is a reasonable subproblem definition.
The question is: can we describe the final solution (Sn ) in terms of subproblems
(Sk)?
1 2 3
Max weight: W = 20 ?
2 4 5
For S4:
Total weight: 14 S5 S4
Maximum benefit: 20 3 5 8
4 3 4
w1 =2 w2 =4 w3 =5 w5 =9
b1 =3 b2 =5 b3 =8 b5 =10 5 9 10
V [k 1, w] if wk w
V [k, w]
max{V [k 1, w],V [k 1, w w k ] bk } else
It means, that the best subset of Sk that has total weight w is:
1) the best subset of Sk-1 that has total weight < w, or
2) the best subset of Sk-1 that has total weight < w-wk plus the
item k
V [k 1, w] if wk w
V [k, w]
max{V [k 1, w],V [k 1, w k w ] k b} else
for w = 0 to W
V[0,w] = 0
for i = 1 to n V[i,0] = 0
for i = 1 to n
for w = 0 to W
if wi <= w // item i can be part of the solution if bi + V[i-1,w-wi] > V[i-
1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
for w = 0 to O(W)
W
V[0,w] = 0
for i = 1 to n
V[i,0] = 0
n = 4 (# of elements)
W = 5 (max weight)
Elements (weight, benefit):
(2,3), (3,4), (4,5), (5,6)
i\ 0 1 2 3 4 5
0W 0 0 0 0 0 0
1
2
3
4
for w = 0 to W
V[0,w] = 0
i\ 0 1 2 3 4 5
0W 0 0 0 0 0 0
1 0
2 0
3 0
4 0
for i = 1 to n
V[i,0] = 0
Items:
1: (2,3)
i\ 0 1 2 3 4 5 i=1 2: (3,4)
0W 0 0 0 0 0 0 3: (4,5)
bi=3
1 0 0 4: (5,6)
wi=2
2 0
w=1
3 0
w-wi =-
4 0
1
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=1 4: (5,6)
0W 0 0 0 0 0 0 bi=3
1 0 0 3
wi=2
2 0
w=2
3 0
w-wi =0
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=1 4: (5,6)
0W 0 0 0 0 0 0 bi=3
1 0 0 3 3
wi=2
2 0
w=3
3 0
w-wi =1
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=1 4: (5,6)
0W 0 0 0 0 0 0 bi=3
1 0 0 3 3 3
wi=2
2 0
w=4
3 0
w-wi =2
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
i\ 3: (4,5)
0 1 2 3 4 5 i=1 4: (5,6)
W
0 0 0 0 0 0 0 bi=3
1 0 0 3 3 3 3
wi=2
2 0
w=5
3 0
w-wi =3
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=2 4: (5,6)
0W 0 0 0 0 0 0 bi=4
1 0 0 3 3 3 3
wi=3
2 0 0
w=1
3 0
w-wi =-
4 0
2
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=2 4: (5,6)
0W 0 0 0 0 0 0 bi=4
1 0 0 3 3 3 3
wi=3
2 0 0 3
w=2
3 0
w-wi =-
4 0
1
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=2 4: (5,6)
0W 0 0 0 0 0 0 bi=4
1 0 0 3 3 3 3
wi=3
2 0 0 3 4
w=3
3 0
w-wi =0
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=2 4: (5,6)
0W 0 0 0 0 0 0 bi=4
1 0 0 3 3 3 3
wi=3
2 0 0 3 4 4
w=4
3 0
w-wi =1
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=2 4: (5,6)
0W 0 0 0 0 0 0 bi=4
1 0 0 3 3 3 3
wi=3
2 0 0 3 4 4 7
w=5
3 0
w-wi =2
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=3 4: (5,6)
0W 0 0 0 0 0 0 bi=5
1 0 0 3 3 3 3
wi=4
2 0 0 3 4 4 7
w= 1..3
3 0 0 3 4
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=3 4: (5,6)
0W 0 0 0 0 0 0 bi=5
1 0 0 3 3 3 3
wi=4
2 0 0 3 4 4 7
w= 4
3 0 0 3 4 5
w- wi=0
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=3 4: (5,6)
0W 0 0 0 0 0 0 bi=5
1 0 0 3 3 3 3
wi=4
2 0 0 3 4 4 7
w= 5
3 0 0 3 4 5 7
w- wi=1
4 0
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=4 4: (5,6)
0W 0 0 0 0 0 0 bi=6
1 0 0 3 3 3 3
wi=5
2 0 0 3 4 4 7
w= 1..4
3 0 0 3 4 5 7
4 0 0 3 4 5
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=4 4: (5,6)
0W 0 0 0 0 0 0 bi=6
1 0 0 3 3 3 3
wi=5
2 0 0 3 4 4 7
w= 5
3 0 0 3 4 5 7
w- wi=0
4 0 0 3 4 5 7
if wi <= w // item i can be part of the solution
if bi + V[i-1,w-wi] > V[i-1,w]
V[i,w] = bi + V[i-1,w- wi]
else
V[i,w] = V[i-1,w]
else V[i,w] = V[i-1,w] // wi > w
All of the information we need is in the table.
V[n,W] is the maximal value of items that can be placed in the
Knapsack.
Let i=n and k=W
if V[i,k] V[i1,k] then
mark the ith item as in the knapsack
i = i1, k = k-wi
else
i = i1 // Assume the ith item is not in the knapsack
// Could it be in the optimally packed knapsack?
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=4 4: (5,6)
0W 0 0 0 0 0 0 k= 5
1 0 0 3 3 3 3 bi=6
2 0 0 3 4 4 7 wi=5
3 0 0 3 4 5 7 V[i,k] = 7
V[i1,k] =7
4 0 0 3 4 5 7
i=n, k=W
while i,k > 0
if V[i,k] V[i1,k] then
mark the ith item as in the knapsack
i = i1, k = k-wi
else
i = i1
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=4 4: (5,6)
0W 0 0 0 0 0 0 k= 5
1 0 0 3 3 3 3 bi=6
2 0 0 3 4 4 7 wi=5
3 0 0 3 4 5 7 V[i,k] = 7
V[i1,k] =7
4 0 0 3 4 5 7
i=n, k=W
while i,k > 0
if V[i,k] V[i1,k] then
mark the ith item as in the knapsack
i = i1, k = k-wi
else
i = i1
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=3 4: (5,6)
0W 0 0 0 0 0 0 k= 5
1 0 0 3 3 3 3 bi=5
2 0 0 3 4 4 7 wi=4
3 0 0 3 4 5 7 V[i,k] = 7
V[i1,k] =7
4 0 0 3 4 5 7
i=n, k=W
while i,k > 0
if V[i,k] V[i1,k] then
mark the ith item as in the knapsack
i = i1, k = k-wi
else
i = i1
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=2 4: (5,6)
0W 0 0 0 0 0 0 k= 5
1 0 0 3 3 3 3 bi=4
2 0 0 3 4 4 7 wi=3
3 0 0 3 4 5 7 V[i,k] = 7
V[i1,k] =3
4 0 0 3 4 5 7
k wi=2
i=n, k=W
while i,k > 0
if V[i,k] V[i1,k] then
mark the ith item as in the knapsack
i = i1, k = k-wi
else
i = i1
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=1 4: (5,6)
0W 0 0 0 0 0 0 k= 2
1 0 0 3 3 3 3 bi=3
2 0 0 3 4 4 7 wi=2
3 0 0 3 4 5 7 V[i,k] = 3
V[i1,k] =0
4 0 0 3 4 5 7
k wi=0
i=n, k=W
while i,k > 0
if V[i,k] V[i1,k] then
mark the ith item as in the knapsack
i = i1, k = k-wi
else
i = i1
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 i=0 4: (5,6)
0W 0 0 0 0 0 0 k= 0
1 0 0 3 3 3 3
2 0 0 3 4 4 7
3 0 0 3 4 5 7 The optimal
knapsack
4 0 0 3 4 5 7
should
i=n, k=W contain {1, 2}
while i,k > 0
if V[i,k] V[i1,k] then
mark the nth item as in the knapsack
i = i1, k = k-wi
else
i = i1
Items:
1: (2,3)
2: (3,4)
3: (4,5)
i\ 0 1 2 3 4 5 4: (5,6)
0W 0 0 0 0 0 0
1 0 0 3 3 3 3
2 0 0 3 4 4 7
3 0 0 3 4 5 7 The optimal
knapsack
4 0 0 3 4 5 7
should
i=n, k=W contain {1, 2}
while i,k > 0
if V[i,k] V[i1,k] then
mark the nth item as in the knapsack
i = i1, k = k-wi
else
i = i1
n = 4 (# of elements)
W = 5 (max weight)
Objective 1 2 1
Choose any number of item such
that the profit is maximized and
2 3 2
constraint is satisfied.
3 4 5
4 5 6
We write the procedure recursively in a natural manner, but
modified to save the result of each subproblem (usually in an
array or hash table).
The procedure now first checks to see whether it has previously
solved this subproblem. If so, it returns the saved value, saving
further computation at this level; if not, the procedure computes
the value in the usual manner.
We say that the recursive procedure has been memoized; it
“remembers” what results it has computed previously.
Goal:
Solve only subproblems that are necessary and solve it only once