Dynamic Programming CISC4080, Computer Algorithms CIS, Fordham Univ. Instructor: X. Zhang
Outline • Introduction via example: Fibonacci, rod cutting • Characteristics of problems that can be solved using dynamic programming • More examples: • Maximal subarray problem • Longest increasing subsequence problem • Two dimensional problem spaces • Longest common subsequence • Matrix chain multiplication • Summary 2
Dynamic Programming 3
Rod Cutting Problem • A company buys long steel rods (of length n), and cuts them into shorter one to sell • integral length only • cutting is free • rods of diff lengths sold for diff. price • Goal: cut rod into shorter ones to sell for maximal profit 4
Rod Cutting Problem • Input: • given rod’s length n • p[i]: selling price of rod of length i, for example: • Output: maximal achievable total settling price, R n, over all possible ways to cut out n to shorter pieces and sell • For example, if n=4, we could cut it into: • {4}: do not cut ==> total selling price is $9 • {3,1} ==> selling price $8+$1=$9 • {2,2} ==> $10 • {2,1,1} ==> $7 multiset: allow duplicate elements • {1,1,1,1}==> $4 order does not matter 5
Solution Space • Evaluate all possible ways, and pick one with highest total selling price? • how many ways to write n as sum of positive integers? • n=4, there are 5 ways: 4=4, 4=1+3, 4=2+2, 4=1+1+1+1, 4=2+1+1 • n=5: … • # of ways to cut n: # of ways to express n as positive integer linear combination of 1,2, …10, 2 n /3 /4 n e π 3 • this leads to exponential running time 6
Thinking Recursively • //return maximum profit achievable with a rod of length n • CutRod (n, p[1…k]) • What’s the smallest problem(s) that we can solve trivially? • if n=0, n=1 • How to reduce the problem to smaller problems? 7
Recursion! • CutRod (n, p[1…k]) //return r n • What’s the smallest problem(s) that we can solve trivially? • if n=0, n=1 • How to reduce the problem to smaller problems? • consider the first rod to cut out and sell, c 1 • c 1 can be 1, 2, 3, … , min (n, k) • we sell it for p[c 1 ], and have a rod of length n-c 1 remaining ==> a smaller problems • Just try all different c 1 and solve subproblems recursively: r n = c 1 =1,2... min { n , k } { p [ c 1 ] + r n − c 1 } max 8
Optimal substructure r n = c 1 =1... min { n , k } { p [ c 1 ] + r n − c 1 } max • Optimal substructure : Optimal solution to a problem of size n incorporates optimal solutions to problems of smaller size (n-1, n-2,… ). 9
Optimal Substructure => recursive solution • //return max. profit one can make with a rod of length n • CutRod (n, p[1…k]) //What’s the smallest problem(s) that we can solve trivially? if n=0 return 0 if n=1 return p[1] //general case: consider the first rod to cut out and sell, curMax=0 for c1=1, 2, 3, … , min (n, k) curProfit = p[c1]+MaxProf (n-c1) curMax = max (curProfit, curMax) // done evaluating all possibilities return curMax 10
Running time? • //return max. profit one can make with a rod of length n • CutRod (n, p[1…k]) //What’s the smallest problem(s) that we can solve trivially? if n=0 return 0 T ( n ) = T ( n − 1) + T ( n − 2) + . . . + T ( n − k ) + C if n=1 // for n > k return p[1] //general case: consider the first rod to cut out and sell, curMax=0 for c1=1, 2, 3, … , min (n, k) curProfit = p[c1]+CutRod (n-c1) curMax = max (curProfit, curMax) // done evaluating all possibilities return curMax 11
Recursive Trees How many times CutRod (2) is called? How about CutRod(1)? 12
Overlapping of Subproblems • Recursive calling tree shows overlapping of subproblems • i.e., n=4 and n=3 share overlapping subproblems (2,1,0) • Idea: avoid recomputing subproblems again and again • store subproblem solutions in memory/table (hence “programming”) 13
Dynamic Programming: two approach • memoization (recursive, top-down) • improve recursive solution by storing subproblem solution in a table • when need solution of a subproblem, check if it has been solved before, • if not, calculate it and store result in table • if yes, access result stored in table • a top-down approach: • start with the problem at hand (a larger problem), and solve subproblems as needed (recursively)
Memoization illustrated in code //return max. profit one can make with a rod of length n CutRod (n, p[1…k]) 1. create an array r[1…n], filled with -1 (indicate “not calculated yet”) 2. CutRodHelper (n, p, r) CutRodHelper (n, p[1…k], r[]) 1. if r[n] >=0 return r[n] //if it has been calculated already 2. // no need to recalculate, return the stored result 3. 4. if n==0 return 0 //base case 5. //general case 6. curMax=0 7. for c1=1, 2, 3, … , min (n, k) 8. curProfit = p[c1] + CutRodHelper (n-c1) 9. curMax = max(curProfit, curMax) 10. 11. r[n]= curMax //save result in r[] for future reference 12. return curMax 15
Dynamic Programming:Tabulation • Memoization (recursive, top-down) • Tabulation • Iteratively solve smaller problems first, move the way up to larger problems • bottom-up method: as we solve smaller problems first, and then larger and larger one • => when solving a problem, all subproblems solutions that are needed have already been calculated
Bottom-up • //return max. profit one can make with a rod of length n • CutRodBottomUp (n, p[1…k]) 1. create an array r[1…n] //store subproblem solutions 2. r[0] = 0 3. for i=1 to n // solve smaller problems first … 4. // calculate r i , max revenue for rod length i 5. curMax=0 6. for c1=1, 2, 3, … , min (i, k) 7. curProfit = p[c1]+ r[i-c1] 8. curMax = max(curProfit, curMax) 9. r[i]= curMax //save result in r[] for future reference 10. 11. return r[n] 17
Recap • We analyze rod cutting problem • Two characteristics of problems that can benefit from dynamic programming: • optimal substructure: a recursive formular r n = c 1 =1,2... min { n , k } { p [ c 1 ] + r n − c 1 } max • overlapping subproblems 18
Recap (2) • How dynamic programming works: • Memoization: recursion with table • Tabulation: iteratively solve all possible subproblems, and work our way from small problems to large problems 19
Exercises • Copy given C++ program for rod cutting • copyRodCut • cd CutRod; Compile and run • Exercise #1: • add some cout statement to find out how many times MaxProf (3) is called when MaxProf(6) is called from main. • Exercise #2: • So far, we focus on finding , max. revenue… r n • but what cutting achieves ? r n • How to extend the functions to output/return the cutting? • e.g., n=4, cutting 2, 2, r_4=… 20
Tracing: CutRod(n=3,p) //return max. profit one can make with a rod of length n CutRod (n, p[1…k]) 1. create an array r[1…n], filled with -1 (indicate “not calculated yet”) 2. CutRodHelper (n, p, r) Tracing with n=3 CutRodHelper (n, p[1…k], r[]) table r : 1. if r[n] >=0 return r[n] //if it has been calculated already c1 2. // no need to recalculate, return the stored result curProfit 3. curMax 4. if n==0 return 0 //base case 5. //general case 6. curMax=0 7. for c1=1, 2, 3, … , min (n, k) 8. curProfit = p[c1] + CutRodHelper (n-c1) 9. curMax = max(curProfit, curMax) 10. 11. r[n]= curMax //save result in r[] for future reference 12. return curMax 21
Tabulation: Tracing n=5 • //return max. profit one can make with a rod of length n • CutRodBottomUp (n, p[1…k]) 1. create an array r[1…n] //store subproblem solutions 2. r[0] = 0 3. for i=1 to n // solve smaller problems first … 4. // calculate r i , max revenue for rod length i 5. curMax=0 6. for c1=1, 2, 3, … , min (i, k) 7. curProfit = p[c1]+ r[i-c1] 8. curMax = max(curProfit, curMax) 9. r[i]= curMax //save result in r[] for future reference 10. 11. return r[n] 22
Discussion: Knapsack • Input • given weight capacity of a knapsack, W • n different objects, with weights and values given by array w[ ], v[ ] • i-th type of objects weighs w[i] and has a value of v[i] • there are infinite quantities of each object type • Output: objects to put into knapsack so that total value is maximized and total weights <= W • For now, focus on max. total value • Discussion: • how is this similar to Rod Cutting? 23
Discussion: Knapsack • Input: weight capacity of a knapsack, W; n different objects, with weights and values given by array w[ ], v[ ] • i-th type of objects weighs w[i] and has a value of v[i] • there are infinite quantities of each object type • Output: objects to put into knapsack so that total value is maximized and total weights <= W • For example: W=13, w[4]={5,3,8,4}, v[4]={10,20,25,8} in the figure • Let V k be max total value possible when weight capacity is k • V 13 = ? Consider first object to put in knapsack: • if object #1 => total max. value would be 10 + max value possible with 13-5 • if object #2 => total max. value would be …. • if object #i => total max. value would be What would be V13? 24
Recommend
More recommend