You are on page 1of 2

Making Change as a Dynamic Programming Problem

/** * Coins: the dynamic programming change algorithm * * Brassard and Bratley, Fundamentals of Algorithmics (1996), pp. 263-64 * * Generate a table from which one can make change optimally from 0 * up to the amount required. The rows are for successively larger * denomination coins/bills, the columns are for the total amount of * change generated. The cell contents show the number of coins used. * * If c[j][k] == c[j-1][k], that signals that denomination[j] is not * included in the coin count for this amount. * * The table is built row by row, starting with a sentinel row zero * containing only zeroes. Within row j at column k (where column k * is greater than or equal to the value of this denomination), we can * compute whether USING one of these coins will generate a smaller * number of coins: c[j-1][k] represents the number of coins if we do * NOT use on of these, while 1 + c[j][k-d[j]] represents the number of * coins if we DO use one of them. * * author Timothy Rolfe, based on Brassard and Bratley */ import java.io.*; public class Coins { // Print out the table in change ? ? static final boolean DEBUG = false; /** * Make change for "amt" units, based on the denominations in d[]. * Dynamic programming solution: in the process, this builds the * table that would solve the change-making process for ALL amounts * up to "amt". The number of coins used is returned through coin[]. * * NOTE: d[] MUST be sorted; presumably d[0] = 1 */ public static void change(int amt, int [] coin, int [] d) { int n = d.length-1; int [][] c = new int[n+1][amt+1]; // Zero-filled int j, k; // Table generation --- dynamic programming portion // c[0][k] remains unchanged at zero as a sentinel row. for ( k = 0; k <= amt; k++ ) c[0][k] = 0; for ( j = 1; j <= n; j++ ) { coin[j] = 0; c[j][0] = 0; // Insure column 0 holds zeroes. for ( k = 1; k <= amt; k++ ) if ( j == 1 ) if ( k < d[j] ) c[j][k] = Integer.MAX_VALUE; else c[j][k] = 1 + c[j][k-d[j]]; else if ( k < d[j] ) c[j][k] = c[j-1][k]; else c[j][k] = Math.min(c[j-1][k], 1 + c[j][k-d[j]]); } if (DEBUG) display(c); j = n; k = amt;

// From the table, get the coins used --- greedy portion while ( k > 0 && j > 0 ) if ( c[j][k] == c[j-1][k] ) // Denom. not used j = j - 1; else // Denom. WAS used { ++coin[j]; k = k - d[j]; } } // For debugging: display the matrix contents static void display (int a[][]) { StringBuffer front = new StringBuffer(" String back; int nrow = a.length, ncol = a[0].length;

");

for ( int row = 0; row < nrow; row++ ) { for ( int col = 0; col < ncol; col++ ) { back = Integer.toString(a[row][col]); if ( back.length() > 3 ) back = "*"; front.setLength(4 - back.length()); System.out.print ( front.toString() + back ); } System.out.println(); }

Printed on 2011-09-12 at 02:57

public static void main ( String[] args ) { int k, amt; /* Debug data set: int [] denom = { 3, 1, 4, 6 }; /**/ /* Alternate debug data set: no nickels: */ int [] denom = { 3, 1, 10, 25 }; /**/ /* Production data set: int [] denom = { 6, 1, 3, 6, 12, 24, 30 }; /**/ int [] coin = new int[denom.length]; System.out.print ("Amount: amt = readInt(); change(amt, coin, denom); for ( k = 1; k < coin.length; k++ ) System.out.println ( (denom[k] < 10 ? " " : "") + denom[k] + ": " + coin[k] + " used."); } // Code for reading console from "Java in a Nutshell", p. 166 // Wrap System.in as a BufferedReader. static BufferedReader console = new BufferedReader (new InputStreamReader(System.in)); public static String readLine() { String rtnVal = ""; try { rtnVal = console.readLine(); } catch (java.io.IOException e) { System.err.println ("File input failed: " + e); System.exit(-1); } return rtnVal; } // end readLine() public static String readLine(BufferedReader inp) { String rtnVal = ""; try { rtnVal = inp.readLine(); } catch (java.io.IOException e) { System.err.println ("File input failed: " + e); System.exit(-1); } return rtnVal; } // end readLine() ");

public static int readInt(BufferedReader inp) { String lineInp = readLine(inp); try { return Integer.parseInt( lineInp.trim() ); } catch (Exception e) { System.err.println (e); System.err.println ("Offending line: " + lineInp); System.err.println ("Returning zero."); return 0; }

} /* Result of a debug run Amount: 9 0 0 0 0 1 2 0 1 2 0 1 2 1: 1 used. 4: 2 used. 6: 0 used. 0 3 3 3 0 4 1 1

public static int readInt() { return readInt(console);

0 5 2 2

0 6 3 1

0 7 4 2

0 8 2 2

0 9 3 3

Result of an alternate debug run (no table) Amount: 30 1: 0 used. 10: 3 used. 25: 0 used. Result of a production run Amount: 53 1: 2 used. 3: 1 used. 6: 0 used. 12: 0 used. 24: 2 used. 30: 0 used. */

You might also like