Upload
janel-stone
View
218
Download
0
Embed Size (px)
Citation preview
Recursion and Dynamic Programming
CSC 172
SPRING 2004
LECTURE 9
Grad TA help sessions?
What is a good time? Office hours are kind of early Would people like Thursdays @ 5ish?
InductionBig-OhRecurrenceCode Style review
Project 1 General Observations Your “style” should travel with you Go to the writing place Some people paraphrased Bently, but got it wrong While big-Oh analysis was not required, some
notion of absraction and generalization is appropriate
Some people lost large amounts because of no disclaimer
Recursive definition
What is a list? A list can be “empty” A list can be an item, followed by a list.
Recursive definition
What is a Tree? A tree can be “empty” A tree can be a node with “children” that are trees.
Recursive definition
What is a number? (integer) A single digit is a number {0,1,2,3,4,5,6,7,8,9} A number is a digit followed by a number
Recursive Definition
What is a simple (4 func) arithmetic expression ? (7+5)* (3-2)
A number is an arithmetic expression If X is an ae, then (X) is an ae If X and Y are both aes, then X+Y , X-Y, X*Y, X/Y are all ae
Recursion We often think of recursion as a “programming
technique” Recursion is also a design pattern for data
structures Recursion is a way to think about problem
solving
A Theological AsideDisclaimer: you don’t have to believe
Can computer science inform theology? Christian notion of “Trinity”? "A three-fold personality existing in one divine
being or substance; the union in one God of Father, Son, and Holy Spirit as three infinite, co-equal, co-eternal persons; one God in three persons."
from about 400 AD to about 1800 AD, countless people were put to death for refusing to believe in the idea of "one God in three persons."
Serpinski TriangleThis design is called Sierpinski's
Triangle, after the Polish mathematician Waclaw Sierpinski who described it in 1916. Among these is its fractal or self-similar character. The large blue triangle consists of three smaller blue triangles, each of which itself consists of three smaller blue triangles, each of which ..., a process of subdivision which could, with adequate screen resolution, be seen to continue indefinitely.
Serpinski Triangle
What is a Serpinski Triangle?
A Serpinski Triangle is a triangle made up of 3 Serpinski triangles.
Weiss’s fundamental rules of recursion1. Base case: always have at least one case that can
be solved without recursion
2. Make progress: Any recursive call must progress toward the base case
3. “You gotta believe”: Always assume that the recursive call works. (In proofs “BTIH”).
4. Compound Interest rule: Never duplicate work by solving the same instance of a problem in separate recursive calls.
Example : Fibonacci Number
// Bad algorithm
public static long fib (int n) {
if (n <= 1)
return n;
else return fib (n-1) + fib(n-2);
}
Why is it bad?
Dynamic Programming If you can mathematically express a problem
recursively, then you can express it as a recursive algorithm.
However, sometimes, this can be inefficiently expressed by a compilerFibonacci numbers
To avoid this recursive “explosion” we can use dynamic programming
Example Problem: Making Change
For a currency with coins C1,C2,…Cn (cents) what is the minimum number of coins needed to make K cents of change?
US currency has 1,5,10, and 25 cent denominationsAnyone got a 50-cent piece?We can make 63 cents by using two quarters & 3
penniesWhat if we had a 21 cent piece?
63 cents
25,25,10,1,1,1
Suppose a 21 cent coin? 21,21,21 is optimal
Recursive Solution
1. If we can make change using exactly one coin, then that is a minimum
2. Otherwise for each possible value j compute the minimum number of coins needed to make j cents in change and K – j cents in change independently. Choose the j that minimizes the sum of the two computations.
public static int makeChange (int[] coins, int change){int minCoins = change;for (int k = 0;k<coins.length;k++)
if (coins[k] == change) return 1;for (int j = 1;j<= change/2;j++) {
int thisCoins = makeChange(coins,j)+makeChange(coins,change-j);
if (thisCoins < minCoins) minCoins = thisCoins;
}return minCoins;
}// How long will this take?
How many calls?63¢
62¢ 2¢1¢ 61¢ 31¢ 32¢. . .
How many calls?63¢
3¢1¢ 4¢ 61¢ 62¢. . .2¢
How many calls?63¢
1¢
3¢1¢ 4¢ 61¢ 62¢. . .2¢
1¢
How many calls?63¢
1¢
3¢1¢ 4¢ 61¢ 62¢. . .2¢
1¢
3¢1¢ 4¢ 61¢. . .2¢
How many times do you call for 2¢?63¢
1¢
3¢1¢ 4¢ 61¢ 62¢. . .2¢
1¢
3¢1¢ 4¢ 61¢. . .2¢
Some Solutions
1(1) & 62(21,21,10,10)
2(1,1) & 61(25,25,10,1)
. . . .
21(21) & 42(21,21)
….
31(21,10) & 32(21,10,1)
Improvements? Limit the inner loops to the coins
1 & 21,21,10,105 & 25,21,10,1,110 & 21,21,10,121 & 21,2125 & 25,10,1,1,1
Still, a recursive branching factor of 5How many times do we solve for 52 cents?
public static int makeChange (int[] coins, int change){
int minCoins = change;
for (int k = 0;k<coins.length;k++)
if (coins[k] == change) return 1;
for (int j = 1;j<= coins.length;j++) {
if (change < coins[j]) continue;
int thisCoins = 1+makeChange(coins,change-coins[j]);
if (thisCoins < minCoins) minCoins = thisCoins;
}
return minCoins;
}// How long will this take?
How many calls?63¢
58¢ 53¢62¢ 42¢ 38¢
48¢ 43¢52¢ 32¢ 13¢
57¢ 52¢61¢ 41¢ 37¢
Tabulation aka Dynamic Programming
Build a table of partial results. The trick is to save answers to the sub-problems in
an array. Use the stored sub-solutions to solve the larger
problems
DP for change making Find optimum solution for 1 cent Find optimum solution for 2 cents using previous Find optimum solution for 3 cents using previous …etc.
At any amount a, for each denomination d, check the minimum coins for the (previously calculated) amount a-d
We can always get from a-d to a with one more coin
public static int makeChange (int[] coins, int differentcoins, int maxChange, int[] coinsUsed, int [] lastCoin){coinsUsed[0] = 0; lastCoin[0]=1;for (int cents = 1; cents <= maxChange; cents++) {
int minCoins = cents; int newCoin = 1;for (int j = 0;j<differentCoins;j++) {
if (coins[j] > cents) continue;if (coinsUsed[cents – coins[j]]+1 < minCoins){
minCoins=coinsUsed[cents – coins[j]]+1;newCoin = coins[j];
}}coinsUsed[cents] = minCoins;lastCoin[cents] = newCoin;
}
Dynamic Programming solution
O(NK) N denominationsK amount of change
By backtracking through the lastCoin[] array, we can generate the sequence needed for the amount in question.