总结:
1、降成一维的思路就是:
m元钱的组合种类为:
用0种 +(只用前1种且至少用了第1种货币)+(只用前2种且至少用了第2种货币)+(只用前3种且至少用了第3种货币)+ ... +(只用前8种且至少用了第8种货币)的总和;
他们之间是互斥的,因此把他们一层一层地计算,然后一层一层地累加起来即可,这样只需要一维数组。
f(n, m) = f(n-1, m) + f(n, m - w[n])
f(n+1, m) = f(n, m) + f(n+1, m - w[n+1])
f(n+1, m) = f(n-1, m) + f(n, m - w[n]) + f(n+1, m - w[n+1])
f(n+1, m) = f(n-2, m) + f(n-1, m - w[n-1]) + f(n, m - w[n]) + f(n+1, m - w[n+1])
f(n+1, m) = ......
f(n+1, m) = f(0, m) + f(0, m - w[0]) + f(1, m - w[1]) + ... + f(n, m - w[n]) + f(n+1, m - w[n+1])
2、当写递推算法出错的时候,要注意查看数组下标的合法性,看下标是否超过了数组的大小,判断下标的边界条件;
其他:
这是一个递推算法;
f(n, m)表示前n种钱币拼凑m元钱的所有不同的情况总数;
f(n, m) = f(n-1, m) + f(n, m - w[n]),其中w[n]位第n元钱的面值大小
容斥原理(并集算法)
A+B-A∩C
f(n, 0)为多少?f(n, 0) = 1
我们考虑以下数值及其公式:
f(1, 1) = f(0, 1) + f(1, 0) = 0 + 1
f(2, 2) = f(1, 2) + f(2, 0) = 1 + 1
f(3, 5) = f(2, 5) + f(3, 0) = 3 + 1
f(4, 10) = f(3, 10) + f(4, 0) = (1+3+4) + 1
以此类推,因此f(n, 0) = 1
此时,开[8][200]的数组,即可。
真的需要开那么多项吗?
像斐波那契用滚动数组,只需要开3项,甚至2项也足以;
这里也可以相应地进行修改。
因为,只用了这一层上一个数和上一层同样位置的数:
i = 1,从1到200标记完
i = 2,从1到200标记完
i = 3,从1到200标记完
i = 4,从1到200标记完
i = 2,从1到200标记完
...
i = 8,从1到200标记完
这样就可以把8项(8种币值的货币)缩小成2项,即可滚动;