[编程题] 拼凑钱币
给你六种面额 1、5、10、20、50、100 元的纸币,假设每种币值的数量都足够多,编写程序求组成N元(N为0~10000的非负整数)的不同组合的个数。
输入描述:
输入包括一个整数n(1 ≤ n ≤ 10000)
输出描述:
输出一个整数,表示不同的组合方案数
输入例子1:
1
输出例子1:
1
分析:其中假设所有的钱币总数为 。总共有 种钱币。我们用 表示用 i 种钱币表示组成 n 元的组合数。我们依次分析12元以内的硬币组合数量。
当我们只使用1种硬币的时候,所有的组合情况如下:
使用硬币数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---|---|---|---|---|---|---|---|---|---|---|---|
只使用1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
1和5 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 3 | 3 |
1、5和10 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 4 | 4 |
依次往下。
当我们增加一种硬币(硬币5)的时候,组合的结果相对于只使用1来说是,在原有只有1的统计基础上行,增加 1 个5元硬币输出的组合情况 + 增加2个5元硬币输出得组合情况 + … + 直到增加到最大的 5 元硬币数量为止。就如具体的取 来说明。
当我们新增加一个5元硬币时,使用硬币5的所有次数取值范围为 。其中 。
我们分情况来考虑:
- 当使用0个5元时,就是上面用1组成数字n的情况;
- 当时用1个5元时,就是上面用1组成数字n-5的情况;
- 当使用2个5元时,就是上面用1组成数字n-2*5的情况。
所以,当使用1和5两种硬币表示数字n=10的时候,就是讲上面的所有情况累加 。总结成通用的公式就如下所示
代码实现如下:
public class Solution {
static int[] values = {1,5,10,20,50,100};
static int combine(int n) {
n++; // 主要是需要多增加一个为0的时候空位,不然会出错
int[][] dp = new int[values.length][n];
for (int i = 0; i < n; i++) {
dp[0][i] = 1;
}
for (int i = 1; i < values.length; i++) {
for (int j = 0,k; j < n; j++) {
k = j/values[i];
while(k>=0){
dp[i][j] += dp[i-1][j-k*values[i]];
k--;
}
System.out.print(dp[i][j]+"\t");
}
System.out.println();
}
return dp[values.length-1][n-1];
}
public static void main(String[] args){
System.out.println(combine(20));
}
}