tags:


10. Dynamic Programming #

Created Tue Aug 6, 2024 at 8:46 PM

#dp

Context #

DP #

DP combines the best of both worlds. Here we search all possibilities (guaranteeing correctness) and store intermediate results (for efficiency) to avoid recomputing. By storing the consequences of all possible decisions and using this information in a systematic way, the total amount of work is minimized.

Info about DP #


Memoization #

Fibonacci example. Exponential algorithm if recursive definition is used. To speed this up, we store the results in an array indexed by the parameter k in F(k). Time taken drops to linear.

Take home lesson: Caching of the results of recursive calls provides most of the benefits of DP, usually including the same running time as the more elegant full solution.

Note:

Removing recursion #

Specifying order - we can get rid of recursion in fibonacci problem by explicitly specifying the order of evaluation of the recurrence relation. Holds for any problem, if we can specify order, then we don’t need recursion.

Example: nCk #

We can do this by the formula by calculating factorials. But suppose we don’t have factorial function available.

We think DP may be possible. So we start by thinking of a recurrence relation. What is nCk. Its the count of all possible subsets of selecting at most k things from n given things.

Since DP is about storing consequences, we think what simplest consequences are related to nCk. We make a story here. Among all subsets that nCk represents, some may have a given element, and some may not, i.e. boolean consequences. Those subsets that have this given element need to choose k-1 from n-1. And those that don’t have it, need to choose k from n-1. Since the possibilities are exhaustive, we can say nCk = (k-1, n-1) + (k-1, n).

We have our recurrence relation. We try to order the evaluation, and can see that an explicit order is possible. Letter represent path of evaluation, right side is values. We don’t need (n, k-1) and only need (n-1, k) and (n-1, k-1), i.e. so is is linearizable.

Applying DP #

There are three steps involved in solving a problem by dynamic programming:

  1. Check optimal substructure and overlapping subproblems exist.
  2. Make a recurrence relation or recursive algorithm. This in inductive, any story would do.
  3. Storage - Show that the number of different parameter values taken on by your recurrence is bounded by a (hopefully small) polynomial.
  4. Remove recursion - Specify an evaluation order for the recurrence so the partial results you need are always available when you need them.