Dynamic Programming
Dynamic Programming Originally the “Tabular Method” Key idea: Problem solution has one or more subproblems that can be solved recursively The subproblems are overlapping The same subproblem will get solved multiple times Solve each subproblem only one time After solving, future attempts just “look up” the solution Can be a tremendous time savings when it applies Compared to divide-and-conquer/recursion, can compute much more Can expand the range of what is feasible to solve dramatically Greedy approaches better, but don’t usually apply
Two approaches to Dynamic Programming Top-Down: The “natural” way to create DP solutions from a recursive one Formulate problem as a recursive problem Need to identify a set of parameters that define the problem state This is usually the key challenge in DP problems Test that it works on simple cases! Every time a function is called, first check to see if that has been computed before If so, just return the pre-computed result If it needs to be computed, compute like usual, but store the result once computed Referred to as “memorization” Usually stored in a table of some sort, but could use map or other structure. Should never have to recompute for those parameters in the future.
Two approaches to Dynamic Programming Bottom-up Again, need to formulate problem as by a state with some parameters Each parameter becomes a “dimension” The “base case” of the table should be easily computed/defined Fill table from base case up to more complex states Each row/col/etc. should need to look at earlier rows/cols/etc. Finally, just look up an entry to find the answer
Comparisons of Methods Top-down: Easier to convert a recursive program to this approach If the exploration of the state space is sparse, can be more efficient Only visits the states that are needed Bottom-up: Avoids repeated function calls – usually just several for-loops Can offer savings in terms of memory: e.g. keep only previous row of table to compute next row
Example: Fibonacci Sequence Top-down: memorize Bottom-up: fill array
Other examples Max 1D Range Sum Longest Increasing Subsequence Coin Change (value, n-numcoins) NP complete problems with fast actual implementations using DP: 0-1 knapsack Traveling Salesman