Topic: | Dynamic Programming (Fib, Squirrels) |
---|---|
Author: | Peter Bui <pbui@cse.nd.edu> |
Date: | October 12, 2009 |
Two ways of looking at dynamic programming:
1. Simplified: Caching results of subproblems in memory to avoid repeated
computation.
2. Advanced: A method for efficiently solving a particular set of search
and optimization problems where greedy algorithms or brute-force would take
much too long.
Often times in a recursive problem such as search or backtracking, we will often repeat a subproblem and thus recompute that result. To avoid this unnecessary computation, save the previous results in lookup table and check that before computing.
Consider the max-cycle-length problem. Consider the fibonacci sequence.
A problem can be broken down into subproblems which are reused multiple times.
When there are multiple recursive subproblems, then branching factor can explode, thus leading to non-polynomial run-time.
static int
fib(int n)
{
if (n == 0) return (0);
if (n == 1) return (1);
return (fib(n - 1) + fib(n - 2));
}
O(2n) exponential run-time.
static int fib_dp(int n)
{
int i;
if (!FT[n])
for (i = 2; i <= n; i++)
if (!FT[i]) FT[i] = FT[i - 1] + FT[i - 2];
return (FT[n]);
}
O(n) linear run-time.
A problem where an optimal solution can be constructed efficiently from optimal solutions to its subproblems:
Let’s say we have a collection of objects called A. For each object o in A we have a “cost,” c(o). Now find the subset of A with the maximum (or minimum) cost, perhaps subject to certain constraints.
Rather than generate all possible subsets O(2n), build a table where at each step we know the best solution thus far.
1. Identify rows and columns: Rows and columns must be discrete units and usually involve the subsets in question.
Given a grid of NxN squares where each square indicates the number of squirrels, determine the total number of squirrels in the path that allows you to hunt the most squirrels as you move from the top left to the bottom right by either going down or right:
Input: Output: 1 5 2 3 6 32 4 3 2 1 2 3 8 4 2 1 0 5 2 3 4 3 1 4 2 1
1. Identify rows and columns: simply the grid containing the squirrel populations.
2. Define recursive relationships:: we want to know which path gives us the largest squirrel population, and since our only valid movements are going down or to the right, this can be defined as:
S(r, c) = Max(S(r, c - 1), S(r - 1, c)) + P(r, c)
3. Building the table does not reveal what the path is, just what the maximum squirrel population is.
2. Table/Matrix Building: use recursive relationships to build the table square by square.
3. Traceback/Reconstruction: use built tables to identify and generate final solution.