题目描述
有数量不限的硬币,币值为25分、10分、5分和1分,请编写代码计算n分有几种表示法。
给定一个int n,请返回n分有几种表示法。保证n小于等于100000,为了防止溢出,请将答案Mod 1000000007。
测试样例:
6
返回:2
递归方法
int MakeChangeCore(int n,int denom)
{
int next_denom=0;
switch(denom)
{
case 25:
next_denom=10;
break;
case 10:
next_denom=5;
break;
case 5:
next_denom=1;
break;
case 1:
return 1;
}
int res=0;
for(int i=0;i*denom<=n;i++)
res+=MakeChangeCore(n-i*denom,next_denom);
return res;
}
//二维dp
public int countWays(int n) {
int A[] = {1, 5, 10, 25}, dp[][] = new int[A.length][n + 1];
for (int j = 0; j <= n; j++) {
dp[0][j] = 1;
}
for (int i = 1; i < A.length; i++) {
for (int j = 0; j <= n; j++) {
int t = j - A[i];
if (t >= 0) {
dp[i][j] = (dp[i - 1][j] + dp[i][t]) % 1000000007;
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[A.length - 1][n];
}
//一维dp
public int countWays(int n) {
int dp[] = new int[n + 1], i, A[] = {1, 5, 10, 25};
for (i = 0, dp[0] = 1; i < A.length; i++) {
for (int j = A[i]; j <= n; j++) {
dp[j] = (dp[j] + dp[j - A[i]]) % 1000000007;
}
}
return dp[n];
}
问题解析 首先如果只用一种硬币的话,那么只有一种解法 接下来,如果我在前一种硬币的基础上又用了一种硬币那么我的解法就变成两种了 好了
我们模拟下 首先我的硬币只有面值1 2 那么我要组合成面值为四 有多少种解法呢 1.我们只用面值1的硬币 那么就是 1 1 1 1
这里就有1种解了 2.接下来我们要用面值为2的硬币在用了面值1硬币的基础上 那么就得在 1 1 后用 2 此时已经有了2种解法了
3.那么此时采用了1个面值为2的硬币啊,按道理说我们是可以用两个面值为2的硬币的,所以我们继续向下走 在 1 2 1 1的基础上
我们来到了第三个位置此时我们放入一个面值2的硬币发现此时是用了1个面值1的硬币 和一个面值2的硬币,所以我们总共的总数还是只能有2种
1 2 2 1 那么接下来我们来到了4的位置 我们又用了1个 面值2的硬币,那么我们得到 了1 2 2 3 为什么呢 我的位置四就有3种了呢
好,让我们来分析分析 第一种那就是全部用面值1的硬币达到了4 第二种是 用面值 1 1 2达到了4 第三种是用了2 2 达到了4
由此我们可以用dp[n+1]来存储结果 首先dp[0] = 1; 为什么我的dp[0]要等于1呢,是因为我们第一次使用某一种
硬币面值的时候需要在0面值的基础上增1,所以我们的dp[0] = 1就是为我们这样服务的。 那么我们再来解析下dp[]数组的含义
他代表着我们前面使用的所有硬币的数量以及到达n种数 1.【1 1 1 1】 2.【1 2 2 1】 3.【1 2 2 3】
1.位置二的1代表我们用了一个面值一的硬币以及我们到达位置2用了两个面值1的硬币
2.位置二的2代表了我们在1.的基础上用了面值2的硬币到达了2所以我们此时就有2种方法 下面给出代码