题目
已知有三种人民币,分别为1元、2元、5元。求10元可以有多少种换成上述三种零钱的方法(不限制每种人民币的数量)。
原理
设有a种面值的人民币,设总价格为b,取a种面值中的一种,设其面值为d,则有:
使用a种面值将总价格b换取零钱的方法数量 =
使用a种面值将总价格(b-d)换取零钱的方法数量 + 使用(a-1)种面值将总价格b换取零钱的方法的数量(其中没有面值d的人民币)
可以对照下表理解原理:
1元 | 1元、2元 | 1元、2元、5元 | ||
---|---|---|---|---|
1, | 1,2 | 1,2,5 | ||
0元 | 0 | 1 | 1 | 1 |
1元 | 1 | 1 | 1 | 1 |
2元 | 2 | 1 | 2 | 2 |
3元 | 3 | 1 | 2 | 2 |
4元 | 4 | 1 | 3 | 3 |
5元 | 5 | 1 | 3 | 4 |
6元 | 6 | 1 | 4 | 5 |
7元 | 7 | 1 | 4 | 6 |
8元 | 8 | 1 | 5 | 7 |
9元 | 9 | 1 | 5 | 8 |
10元 | 10 | 1 | 6 | 10 |
如果设上表为二维数组A,横向表头取值1
、1,2
,1,2,5
,纵向表头取值为1~10
。一些具体的等式如下:
A[2][1,2] = A[0][1,2] + A[2][1] = 1 + 1 = 2
A[3][1,2] = A[1][1,2] + A[3][1] = 1 + 1 = 2
A[4][1,2] = A[2][1,2] + A[4][1] = 2 + 1 = 3
A[5][1,2] = A[3][1,2] + A[5][1] = 2 + 1 = 3
A[6][1,2] = A[4][1,2] + A[6][1] = 3 + 1 = 4
A[5][1,2,5] = A[0][1,2,5] + A[5][1,2] = 1 + 3 = 4
A[6][1,2,5] = A[1][1,2,5] + A[6][1,2] = 1 + 4 = 5
A[9][1,2,5] = A[4][1,2,5] + A[9][1,2] = 3 + 5 = 8
A[10][1,2,5] = A[5][1,2,5] + A[10][1,2] = 4 + 6 = 10
代码
如果理解了原理,那么代码很简单。唯一需要注意的是,我们不需要保存中间量,因此一维数组完全可以胜任,秘密在于分层计算,这一步累加最为重要A[j] += A[j - kind[i]];
#include <stdio.h>
int count_change(int n)
{
int A[n + 1];
int kind[3] = {1, 2, 5};
A[0] = 1;
for (int j = 1; j <= n; j++)
A[j] = 0;
for (int i = 0; i < 3; i++)
{
for (int j = kind[i]; j <= n; j++)
{
A[j] += A[j - kind[i]];
}
for (int j = 0; j <= n; j++)
{
printf("%d ", A[j]);
}
printf("
");
}
return A[n];
}
int main(void)
{
int result = count_change(10);
printf("%d
", result);
return 0;
}