您的位置:首页 > 其它

硬币组合问题

2014-08-31 01:42 211 查看
问题描述:

Once the machines take over, the denomination of every coin will be a power of two: 1-cent, 2-cent, 4-cent, 8-cent, 16-cent, etc. There will
be no limit to how much a coin can be worth.

A set of coins makes change for n if the sum of the values of the coins is n. For example, the following sets make change for 7:

7 1-cent coins

5 1-cent, 1 2-cent coins

3 1-cent, 2 2-cent coins

3 1-cent, 1 4-cent coins

1 1-cent, 3 2-cent coins

1 1-cent, 1 2-cent, 1 4-cent coins

Thus, there are 6 ways to make change for 7. Write a function count_change that takes a positive integer n and returns the number of ways to make
change for n using these coins of the future:

def count_change(amount):

"""Return the number of ways to make change for amount.

>>> count_change(7)

6

>>> count_change(10)

14

>>> count_change(20)

60

>>> count_change(100)

9828

"""

问题思路来自最基本的硬币组合问题,可用动态规划解决,关键是要搞清楚递归子问题的划分,http://www.algorithmist.com/index.php/Coin_Change

动态规划问题应具备两个要素:

1. 最优子结构

如果一个问题的最优解包含其自问题的最优解,我们就称子问题具有最优子结构性质。

2. 重叠子问题

子问题空间必须足够小,即问题的递归算法会反复的求解相同的子问题而不是一直生成新的子问题。

Java实现代码如下,没有用Python,Python实现类似:

public class CountChange {
public int countChange(int amount, int dim, int[][] count) {
int q;
//三种base cases
if (amount == 0) return 1;//没钱了,所以就一种solution,就是不用任何硬币
if (amount < 0) return 0;//钱总额小于0,不可能有solution
if (amount >= 0 && dim < 0) return 0;//钱数大于等于0,但维数小于0,也就是没有coinset存在,也不可能有solution

if (count[amount][dim] >= 0) return count[amount][dim];//如果memo里面已经计算过相应情况的组合数目,那么直接返回。

q = countChange(amount, dim - 1, count) + countChange((int)(amount - Math.pow(2, dim)), dim, count);//具体可见链接http://www.algorithmist.com/index.php/Coin_Change,解释有点复杂。这个就是这个问题比较难得递归分类问题
count[amount][dim] = q;
return q;
}
public int count(int amount) {
int dim = (int)(Math.log(amount) / Math.log(2));//dim表示最大银币面值的指数,也就是2的dim次为最大面值。他也是组成coinset的维数
int[][] count = new int[amount + 1][dim + 1];//设置一个memo,count[i][j]表示总额为i时,利用维数为j的时候一共有多少种组合方式。
for (int i = 0; i <= amount; i++)
for (int j = 0; j <= dim; j++)
count[i][j] = -1;
return countChange(amount, dim, count);
}
public static void main(String[] args) {
CountChange t = new CountChange();
int c = t.count(20);
System.out.println(c);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: