在硬币兑换中找到多种方法来计算总和?

Posted

技术标签:

【中文标题】在硬币兑换中找到多种方法来计算总和?【英文标题】:Finding number of ways to make a sum in coin changing? 【发布时间】:2015-06-18 08:30:55 【问题描述】:

给定一个 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 个楼梯,我必须计算总数从底部到达顶部的方法。为什么我们不能在这个问题中使用类似的方法?

【问题讨论】:

你为什么不尝试实现这个想法,然后把它放在这里?我认为我们没有任何规则不使用任何类型的方法/想法。 我想问的是,这会是解决这个问题的正确方法吗?此外,我并不是要你帮我编写问题或调试一些代码,我只想知道,这是否是解决上述问题的正确方法? 这行不通,因为您可能会添加相同的案例(假设顺序被忽略)。 动态编程通常被称为递归的替代方案。话虽如此,您能想一想递归解决方案与您的想法有何不同吗? 重点是,最好看看你的实现并告诉你哪里出了问题。仅凭您的描述,很难说什么(至少是伪代码)。同意吗? 【参考方案1】:

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

这行不通,因为在 n 楼梯问题中,顺序很重要。例如如果您爬 5 级楼梯,则 1, 2, 1, 1 与 1, 1, 2, 1 不同。

但是在找零问题中,只有每个硬币的总计数,而不是你添加它们的顺序,所以如果你赚 5 美元,$1, $2, $1, $1 与 $1, $1, 2 美元,1 美元。因此,简单的记忆方法不起作用,您需要存储到达 arr[i] 的所有可能方式,而不仅仅是总数。

例如,假设您试图用 1 美元和 2 美元赚 6 美元。你不能把赚 4 美元的方法的数量加到赚 5 美元的方法的数量上,因为(例如)赚 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 不应单独计算。

【讨论】:

对。我该怎么做?我是否应该在每个步骤中继续存储所有可能的解决方案? 只要存储一个元组,其值与每个解决方案的硬币数一样多。没那么复杂。 知道了。惊人的例子。清除了一切。 @samgak,非常感谢您的帮助。非常感谢。【参考方案2】:

Samgak 的回答解释了进行更改与一次爬 1 或 2 步楼梯的不同之处:更改的顺序并不重要,但爬楼梯时的顺序很重要。

你可以使用动态规划来解决这个问题,但是你需要一个更复杂的状态。设a[i][j] 为 i 单位货币找零的方法数,仅使用前 j 个面额的硬币。所以,a[0][0]=1a[i][0] = 0,对于 i 大于 0,对于 j 大于 0,a[i][j] = a[i][j-1] + a[i-Sj][j-1] + a[i-2*Sj][j-1]+...

【讨论】:

以上是关于在硬币兑换中找到多种方法来计算总和?的主要内容,如果未能解决你的问题,请参考以下文章

贪婪算法之兑换硬币及问题所在

8P-钱币兑换问题

322-零钱兑换

钱币兑换问题

322-零钱兑换(完全背包)

零钱兑换