CSE 40872 Lecture 016

Topic:Dynamic Programming (Fib, Squirrels)
Author: Peter Bui <pbui@cse.nd.edu>
Date: October 12, 2009

Dynamic Programming

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.

Caching

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.

Overlapping Subproblems

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.

Fibonacci Sequence

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.

Fibonacci Sequence (DP)

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.

Fibonacci Sequence (src)

Fib Source Code

Optimal Substructure

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.

Approach

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.

  1. Define recursive relationships: How does one square depend on another?

Squirrel Hunting

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

Squirrel Hunting

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)

Squirrel Hunting (src)

Squirrel Source Code

Squirrel Hunting (Notes)

  1. Each S(r, c) contains the optimal solution for that square.
  2. Final solution is in the final corner: S(n, n).

3. Building the table does not reveal what the path is, just what the maximum squirrel population is.

Template

  1. Initialization: pad the first row and column with initial values.

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.

Additional Resources