Given a value N, if we want to make change for N cents, and we have infinite supply of each of S = { S1, S2, .. , Sm} valued coins, how many ways can we make the change? The order of coins doesn’t matter.
From http://www.algorithmist.com/index.php/Coin_Change
To count total number solutions, we can divide all set solutions in two sets.
1) Solutions that do not contain mth coin (or Sm).
2) Solutions that contain at least one Sm.
Let count(S[], m, n) be the function to count the number of solutions, then it can be written as sum of count(S[], m-1, n) and count(S[], m, n-Sm).
It just uses previous row, same column value, and same row, previous columns(this is always kept).
http://www.zrzahid.com/coin-sum-problem-dynamic-programming/
Read full article from Dynamic Programming | Set 7 (Coin Change) | GeeksforGeeks
From http://www.algorithmist.com/index.php/Coin_Change
To count total number solutions, we can divide all set solutions in two sets.
1) Solutions that do not contain mth coin (or Sm).
2) Solutions that contain at least one Sm.
Let count(S[], m, n) be the function to count the number of solutions, then it can be written as sum of count(S[], m-1, n) and count(S[], m, n-Sm).
Recursive Formulation
We are trying to count the number of distinct sets.
Since order does not matter, we will impose that our solutions (sets) are all sorted in non-decreasing order (Thus, we are looking at sorted-set solutions: collections).
For a particular N and (now with the restriction that , our solutions can be constructed in non-decreasing order), the set of solutions for this problem, C(N,m), can be partitioned into two sets:
- There are those sets that do not contain any Sm and
- Those sets that contain at least 1 Sm
This partitioning will essentially break the initial problem into two subproblems:
- If N < Sm (that is, a solution does not contain Sm), then we can solve the subproblem of N with , or the solutions ofC(N,m - 1).
- If (that is, a solution does in fact contain Sm), then we are using at least one Sm, thus we are now solving the subproblem of N - Sm, . This is C(N - Sm,m).
Thus, we can formulate the following:
C(N,m) = C(N,m - 1) + C(N - Sm,m)
Time Complexity: O(mn)
int
count(
int
S[],
int
m,
int
n )
{
int
i, j, x, y;
// We need n+1 rows as the table is consturcted in bottom up manner using
// the base case 0 value case (n = 0)
int
table[n+1][m];
// Fill the enteries for 0 value case (n = 0)
for
(i=0; i<m; i++)
table[0][i] = 1;
// Fill rest of the table enteries in bottom up manner
for
(i = 1; i < n+1; i++)
{
for
(j = 0; j < m; j++)
{
// Count of solutions including S[j]
x = (i-S[j] >= 0)? table[i - S[j]][j]: 0;
// Count of solutions excluding S[j]
y = (j >= 1)? table[i][j-1]: 0;
// total count
table[i][j] = x + y;
}
}
return
table[n][m-1];
}
Following is a simplified version of method 2. The auxiliary space required here is O(n) only.
http://stackoverflow.com/questions/27880842/space-optimized-solution-for-coin-changeIt just uses previous row, same column value, and same row, previous columns(this is always kept).
int count( int S[], int m, int n ) { // table[i] will be storing the number of solutions for // value i. We need n+1 rows as the table is consturcted // in bottom up manner using the base case (n = 0) int table[n+1]; // Initialize all table values as 0 memset (table, 0, sizeof (table)); // Base case (If given value is 0) table[0] = 1; // Pick all coins one by one and update the table[] values // after the index greater than or equal to the value of the // picked coin for ( int i=0; i<m; i++) for ( int j=S[i]; j<=n; j++) table[j] += table[j-S[i]]; return table[n]; } |
Optimal Substructure
We can see that we can find the number ways we can make n using C={ c1, c2, .. , cm} coins by combining solution of making (n-cm) and including last coin cm to current solution; or we can simply ignore the last coin cm and try to find solution with remaining coins.
We can see that we can find the number ways we can make n using C={ c1, c2, .. , cm} coins by combining solution of making (n-cm) and including last coin cm to current solution; or we can simply ignore the last coin cm and try to find solution with remaining coins.
let, cs(C, n, m) be the number of solutions of making n using m coins C = {c1, c2, …, cm}. The we can write the following recursive formula,
cs(C, n, m) = cs(C, n-cm, m) + cs(C, n, m-1).
public static int coinSum(final int[] coins, final int sum) { final int m = coins.length; final int[][] csTable = new int[sum + 1][m + 1]; // base cases: if m == 0 then no solution for any sum for (int i = 0; i <= sum; i++) { csTable[i][0] = 0; } // base case: if sum = 0 then there is only one solution for any input set: just take none of each of the items. for (int j = 0; j <= m; j++) { csTable[0][j] = 1; } for (int i = 1; i <= sum; i++) { for (int j = 1; j <= m; j++) { // solutions excluding coins[j] final int s1 = csTable[i][j - 1]; // solutions including coins[j] // look at the column index in csTable[i - coins[j - 1]][j]. This is not j-1 as we can use as much coin // of type j as we like. final int s2 = (i - coins[j - 1]) >= 0 ? csTable[i - coins[j - 1]][j] : 0; csTable[i][j] = s1 + s2; } } return csTable[sum][m]; }Also refer to http://www.algorithmist.com/index.php/Coin_Change
Read full article from Dynamic Programming | Set 7 (Coin Change) | GeeksforGeeks