找到改变硬币总和的方法数量?

时间:2015-06-18 08:30:55

标签: c++ algorithm dynamic-programming

给定值N,如果我们想要改变N美分,并且我们每个S = {S1,S2,..,Sm}值的硬币都有无限供应,我们可以通过多少方式进行更改?硬币的顺序无关紧要。

例如,对于N = 4和S = {1,2,3},有四个解:{1,1,1,1},{1,1,2},{2,2}, {1,3}。因此输出应为4.对于N = 10且S = {2,5,3,6},有五种解决方案:{2,2,2,2,2},{2,2,3,3}, {2,2,6},{2,3,5}和{5,5}。所以输出应该是5。

现在,我有一个疑问。为什么我们不能做类似的事情,

arr[i] = arr[i-1] + arr[i-2] + arr[i-3]

基本上,arr[i]存储了总和i的方法数。我在这里给出的方法有点类似于n stairs problem,我可以爬上一定数量的楼梯,也就是说,让我们一次说1个楼梯或者一次2个楼梯,我必须计算从底部到达顶部的总方式。为什么我们不能在这个问题中使用类似的方法?

2 个答案:

答案 0 :(得分:4)

  

为什么我们不能在这个问题中使用类似的方法?

它不会起作用,因为在n阶梯问题中,顺序很重要。对于例如如果你爬5级楼梯,{1,2,1,1}被计为与{1,1,2,1}不同。

然而,在制作更改问题中,只有每个硬币的总计数,而不是你添加的顺序,所以如果你赚5美元,{$ 1,$ 2,$ 1,$ 1}与{$ 1,$ 1相同, 2美元,1美元。因此,简单的记忆方法不起作用,你需要存储所有可能的方法来达到arr [i],而不仅仅是总数。

例如,假设你试图用$ 1和$ 2赚6美元。您不能仅仅为赚取5美元的方式添加4美元的方式,因为(例如)4美元的一种方式是{$ 1,$ 1,$ 2}(你可以加2美元)要赚6美元即{$ 1,$ 1,$ 2,$ 2}),其中一种赚5美元的方式是{$ 1,$ 2,$ 2}(你可以加1美元赚6美元{$ 1,$ 2,$ 2,$ 1 })。

但{$ 1,$ 2,$ 2,$ 1}和{$ 1,$ 1,$ 2,$ 2}不应单独计算。

答案 1 :(得分:3)

Samgak的回答解释了如何使改变与攀爬楼梯一步一步或两步不同:订单对于进行更改并不重要,但是当您爬楼梯时,订单很重要。

您可以使用动态编程来解决问题,但需要更复杂的状态。让a[i][j]成为使用硬币的前j个面额来改变i单位货币的方法的数量。因此,对于i大于0,a[0][0]=1a[i][0] = 0,对于大于0的j,a[i][j] = a[i][j-1] + a[i-Sj][j-1] + a[i-2*Sj][j-1]+...