Given a number of dollars, , and a list of dollar values for distinct coins, , find and print the number of different ways you can make change for dollars if each coin is available in an infinite quantity.
Hints:
- You can solve this problem recursively, but you must optimize your solution to eliminate overlapping subproblems using Dynamic Programming if you wish to pass all test cases. More specifically, think of ways to store the checked solutions and use the stored values to avoid repeatedly calculating the same values.
- Think about the degenerate cases:
- How many ways can you make change for dollars?
- How many ways can you make change for less than dollars if you have no coins?
- If you are having trouble defining the storage for your precomputed values, then think about it in terms of the base case .
Input Format
The first line contain two space-separated integers describing the respective values of and .
The second line contains space-separated integers describing the respective values of , where each integer denotes the dollar value of a distinct coin available in an infinite quantity.
The second line contains space-separated integers describing the respective values of , where each integer denotes the dollar value of a distinct coin available in an infinite quantity.
Constraints
- The list of coins contains distinct integers where each integer denotes the dollar value of a coin available in an infinite quantity.
Output Format
Print a single integer denoting the number of ways we can make change for dollars using an infinite supply of our types of coins.
Sample Input 0
4 3
1 2 3
Sample Output 0
4
Explanation 0
For and there are four solutions:
For and there are four solutions:
Thus, we print on a new line.
Sample Input 1
10 4
2 5 3 6
Sample Output 1
5
Explanation 1
For and there are five solutions:
For and there are five solutions:
Thus, we print on a new line.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | package dp; import java.util.Scanner; /** * first successful story by analyzing it and coming up an algorithm by myself * --even though I saw this question before, I basically forgot. * Them came up a acceptable solution within 15 minutes. * * Cheers to myself. * @author Andrew Ma * */ public class CoinChangeNumOfWays { public static long makeChange(int[] coins, int money) { //I assumes 0 denom having 0 solutions to any amount of money //also assumes any denom having 0 solution to 0 amount of money //it turns out to be right! to be brave to make assumptions! //making room for 0 denom and 0 amount of money long dp[][] = new long[coins.length+1][money+1]; //initialization the known solutions //0 denom for(int i=0;i<money+1;i++){ dp[0][i]=0;//no solution for each money value } //0 money value for(int i=0;i<coins.length+1;i++){ dp[i][0]=0;//no coin can do 0 change } //then build up values towards to final solution //c and m here are for dp array's dimensions /* * define dp[c][m] as accumulated solutions at c and m * dp[c][m]= * 1. dp[c-1][m]. when money value is less than denom, then get solution from last denom * --here it needs to have a 0 denom * 2. dp[c-1][m]+1. when money value equals denom value, we get one more solution * 3. dp[c-1][m] + dp[c][m-coins[c-1]]. when money valus is greater than denom value, * it adds up accumulation from previous denom and same denom for meney value * not including this denom. * damn, when did I become so able to analyze? I guess drawing it out and practice on paper or white board * really helped to see one's thoughts and then you just need to write the code to reflect the thoughts. * and you are confident that you are able to write code to reflect your thoughts. */ for(int c=1;c<coins.length+1;c++){ for(int m=1;m<money+1;m++){ //when it comes to refer values in coins, c need to be converted back to 0 based if(m<coins[c-1]){ //no change at this, copy the last denom's accumulated solutions dp[c][m] = dp[c-1][m]; } else if(m==coins[c-1]){ //we get one more solution dp[c][m] = dp[c-1][m] +1; } else //if (m>coins[c-1]) { //then it is last denom's accumulated solution + lesser value's accumulated solution dp[c][m] = dp[c-1][m] + dp[c][m-coins[c-1]]; } } } return dp[coins.length][money]; } public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int m = in.nextInt(); int coins[] = new int[m]; for(int coins_i=0; coins_i < m; coins_i++){ coins[coins_i] = in.nextInt(); } System.out.println(makeChange(coins, n)); } } |
No comments:
Post a Comment