Rod cutting Decide where to cut steel rods: Given a rod of length n inches and a table of prices pi, i=1,2,…,n, find the maximum revenue rn obtainable by cutting up the rod and selling the pieces Rod lengths are integers For i=1,2,…,n we know the price pi of a rod of length i inches
For a rod of length 4: 2+2 is optimal (p2+p2=10) Example For a rod of length 4: 2+2 is optimal (p2+p2=10) In general, can cut a rod of length n 2n-1 ways length i 1 2 3 4 5 6 7 8 9 10 price pi 17 20 24 30
Example: rod of length 4 length i 1 2 3 4 5 6 7 8 9 10 price pi 17 20 24 30 Cuts Revenue 4 9 1, 3 1 + 8 = 9 2, 2 5 + 5 = 10 3, 1 8 + 1 = 9 1, 1, 2 1 + 1 + 5 = 7 1, 2, 1 1 + 5 + 1 = 7 2, 1, 1 5 + 1 + 1 = 7 1, 1, 1, 1 1 + 1 + 1 + 1 = 4 Best: two 2-inch pieces = revenue of p2+p2=5+5=10
Calculating Maximum Revenue length i 1 2 3 4 5 6 7 8 9 10 price pi 17 20 24 30 i ri optimal solution 1 1 (no cuts) 2 5 2 (no cuts) 3 8 3 (no cuts) 4 10 2 + 2 13 2 + 3 6 17 6 (no cuts) 7 18 1 + 6 or 2 + 2 + 3 22 2 + 6
General Solution If optimal solution cuts rod in k pieces then optimal decomposition: n=i1+i2+…+ik Revenue: rn=pi1+pi2+…+pik In general: rn=max{pn,r1+rn-1,r2+rn-2,…,rn-1+r1} Initial cut of the rod: two pieces of size i and n-i Revenue ri and rn-i from those two pieces Need to consider all possible values of i May get better revenue if we sell the rod uncut
A different view of the problem Decomposition in A first, left-hand piece of length i A right-hand reminder of length n-i Only the reminder is further divided Then rn=max{pi+rn-i, 1 <= i <= n} Thus, need solution to only one subproblem
Caclulating Maximum Revenue Better comparison: rk=max(pi+rk−i) over all 1≤i≤k i ri Maximum of 1 r1 p1+r0 2 r2 p1+r1,p2+r0 3 r3 p1+r2,p2+r1,p3+r0 4 10 p1+r3,p2+r2,p3+r1,p4+r0 ...
Top-down implementation CUT-ROD(p,n) if n==0 return 0 q = -∞ for i=1 to n q=max{q,p[i]+CUT-ROD(p,n-i)} return q Time recurrence: T(n)=1+T(1)+T(2)+…+T(n-1) T(n)=O(2n)
Dynamic Programming Problem with recursive solution: subproblems solved multiple times Must figure out a way to solve each subproblem just once Two possible solutions: solve a subproblem and remember its solution Top Down: Memoize recursive algorithm Bottom Up: Figure out optimum order to fill the solution array
Rod Cutting: Bottom Up Solution Optimality of subproblems is obvious DP-CUT-ROD(p,n) let r[0..n], s[0..n] be new arrays r[0]=0 for j=1 to n q=-∞ for i=1 to j if q < p[i]+r[j-i] s[j]=i; q= p[i]+r[j-i] r[j]=q return r and s
Retrieving an optimal solution PRINT-CUT-ROD (r,s) = DP-CUT-ROD(p,n) while n>0 print s[n] n=n-s[n] Example: i 0 1 2 3 4 5 6 7 r[i] 0 1 5 8 10 13 17 18 s[i] 0 1 2 3 2 2 6 1
Memoize Make functions faster by trading space for time `Memoizing' - caching the return values of the function in a table. If you call the function again with the same arguments, memoize gives you the value out of the table, instead of letting the function compute the value all over again.
Fibonacci int RegularFib(int n) { if (n == 0 || n == 1) return n; else return RegularFib(n - 1) + RegularFib(n - 2); }
Fibonacci
Fibonacci Memoized solution int MemoizeFib(int n){ if(n == 0) return 0; if (n == 1 || n == 2) return 1; if(helperMemory[n] != 0) return helperMemory[n]; else { helperMemory[n] = MemoizeFib(n-1) + MemoizeFib(n-2); }
Fibonacci
Rod cut Top Down Memoized Solution Store solution to subproblem of length i in array element r(i) MemoizedCutRod(p, n) r[n]=(0 => 0, others =>MinInt) return MemoizedCutRodAux(p, n, r) MemoizedCutRodAux(p, n, r) if r[n] = 0 and then n != 0 then q = -∞ for i=1 to n q := max(q, p[i] + MemoizedCutRodAux(p, n-i, r)) r[n] = q return r[n]