Lecture Notes on 27 Apr 2022 Dynamic Programming is a computational problem solving paradigm that relies on two factors - overlapping sub-problems and optimal substructure. In dynamic programming you break a problem into sub-problems and use the optimal solution of the sub-problems to solve the main problem. In dynamic programming you store the results of the sub-problems so that you do not repeat the same computations (otherwise known as memoization). A great example of overlapping sub-problems is the computation of terms in the Fibonacci series. The general term in the Fibonacci series can be written as fib (n) = fib (n - 1) + fib (n - 2) fib (n - 1) = fib (n - 2) + fib (n - 3) fib (n - 2) = fib (n - 3) + fin (n - 4) A problem must have optimal substructure property if it can be solved by dynamic programming. Consider the shortest path algorithm that we did last class. If a vertex q lies on the shortest path from p to r then the shortest path from p to r is the sum of the shortest path from p to q and the shortest path from q to r. Here is a worksheet for the classic rod cutting problem: https://www.cs.utexas.edu/users/mitra/csSpring2022/cs313/notes/Rod_Cutting_Problem.pdf https://www.cs.utexas.edu/users/mitra/csSpring2022/cs313/notes/Rod_Cutting_Problem.docx Code for the Rod Cutting Problem def cut_rod (p, n): r = [] s = [] for i in range (n + 1): r.append (0) s.append (0) for j in range (1, n + 1): max_price = -1 for k in range (1, j + 1): new_price = 0 if (k < len(p)): new_price = p[k] + r[j - k] else: new_price = r[j - k] if (new_price > max_price): max_price = new_price # remember the best value of the cut s[j] = k r[j] = max_price print (r) print (s) return r, s def main(): # define the price per length of rod p = [0, 1, 5, 8, 9, 10, 17, 17, 20] # prompt the user to enter the size of the rod to be cut n = int (input ("Enter size of rod: ")) # get the optimal price for cutting a rod of length n r, s = cut_rod (p, n) # print the optimal price print ("Optimal price = ", r[n]) # print the cuts of the rod while (n > 0): print (s[n]) n = n - s[n] main() Code for Number of Cuts for a Given Rod Size: def main(): dim = int (input ("Enter dimension of grid: ")) cuts = [] for i in range (dim + 1): row = [] for j in range (dim + 1): row.append (0) cuts.append (row) for i in range (dim + 1): for j in range (dim + 1): if (i == 0) and (j == 0): cuts[i][j] = 1 else: if (i > j): cuts[i][j] = cuts[i - 1][j] else: cuts[i][j] = cuts[i - 1][j] + cuts[i][j - i] # now print the grid for i in range (dim + 1): for j in range (dim + 1): print (cuts[i][j], end = " ") print () print () main()