public class Coins_dp { static int M[]; // M[j] = min # coins used to make change for $j /* ============================================================= make_M(v, M): make the M[] array v[] = values of each type of coin M[j] = min # coins used to make change for $j Return: the value M[C] (which is the min # coins used to make change for $C ============================================================= */ static int make_M(int[] v, int M[]) { int sol; int j, k, min; /* --------------------------- Base cases --------------------------- */ M[0] = 0; // 0 coins needed to make change for $0 /* --------------------------------------------------- The other cases (starting from 1 to M.length - 1) --------------------------------------------------- */ for ( j = 1; j < M.length; j++ ) { if ( M.length < 20 ) System.out.println("\nComputing M[" + j + "]"); /* ========================================================== When for any value j, we have the solutions for: M[0] M[1] ... M[j-1] M[x] = min # coins used to make change for $x We can compute M[i] as: M[j] = min( M[j - v[k]] + 1 ) k = 0, 1, 2, ..., i-1 ========================================================== */ sol = M[j - v[0]]; // Try one coin of denomination 0 // with value v[0] = 1 min = sol + 1; // Best solution so far... if ( M.length < 20 ) System.out.println(" " + (sol+1) ); for ( k = 1; k < v.length; k++ ) { /* -------------------------------------------- Check if we can use the k-th denomination -------------------------------------------- */ if ( v[k] <= j ) { /* ------------------------ Divide step ------------------------ */ sol = M[j - v[k]]; // Try one coin of denomination k // with value v[k] if ( M.length < 20 ) System.out.println(" " + (sol+1) ); /* --------------------------------------- Conquer: solve original problem using solution from smaller problems --------------------------------------- */ if ( sol + 1 < min ) min = sol + 1; // New best solution so far } } M[j] = min; if ( M.length < 20 ) System.out.println("=====> M[" + j + "] = " + M[j]); } return( M[M.length-1] ); } public static void main(String[] args) { // int[] v = {1, 5, 10, 25, 50, 100, 500}; int[] v = {1, 3, 9, 19, 26 }; int C, r, i; C = 65; // Around 53 it starts to slow... M = new int[ C + 1 ]; r = make_M(v, M); /* for (i = 0; i <= C; i ++) System.out.println("M[" + i + "] = " + M[i]); */ System.out.println("Min # coins to make change for " + C + " = " + r); } }