algorithm - 找零的方式数 N

标签 algorithm dynamic-programming

我遇到了这个问题:

http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/

Given a value N, if we want to make change for N cents, and we have infinite supply of each of S = { S1, S2, .. , Sm} valued coins, how many ways can we make the change? The order of coins doesn’t matter.

For example, for N = 4 and S = {1,2,3}, there are four solutions: {1,1,1,1},{1,1,2},{2,2},{1,3}. So output should be 4. For N = 10 and S = {2, 5, 3, 6}, there are five solutions: {2,2,2,2,2}, {2,2,3,3}, {2,2,6}, {2,3,5} and {5,5}. So the output should be 5.

我想到了解决方案:

// recurrence relation
count[N] = count[N-d] for all denomination <= N

Source code
-----------

public static int numWays(int N, int[] denoms) {
  if (N == 0)
     return 0;
  
  int[] ways = new int[N+1];
  ways[0] = 1;
  
  for (int i=1; i<=N; i++) {
     ways[i] = 0;
     for (int d : denoms) {
        if (d <= i) {
           ways[i] += ways[i-d];
        }
     }
  }
  
  return ways[N];
}

但这会计算面额相同但顺序不同的重复项。例如,如果 denominations = {1,2} 且 N=3,则它计算 {1,1,1}、{2,1}、{1,2} 其中有重复条目 {1,2}。

我看到链接中描述的 DP 解决方案 here避免重复。我理解递归关系是如何工作的,但我无法理解它是如何避免重复的,而我的解决方案却没有。请解释背后的想法。

最佳答案

C(i, j) 是使用面额为 S1, ..., Sj 的硬币使总数 i 的方法数>。您的代码实现了以下循环(有序方式)。

C(i, m) | i <  0 = 0
        | i == 0 = 1
        | i >  0 = sum_{j = 1}^m C(i - Sj, m)

链接代码实现了不同的循环(无序方式)。

C(i, j) | i <  0           = 0
        | i == 0           = 1
        | i >  0 && j <= 0 = 0
        | i >  0 && j >  0 = C(i - Sj, j) + C(i, j - 1)

这两个代码之间的区别很微妙:或多或少只是循环的嵌套方式。在继续 i + 1 之前,您添加了 i 的所有术语,但是链接代码为每个 添加了 j 术语i,然后是每个 ij + 1 项,等等。因此,当链接代码考虑使用面额的可能性时 - Sj coin from subtotal i,它隐含地只考虑那些继续使用面额硬币 S1, ..., Sj 的解决方案,因为当前总数对于 i - Sj 不包括使用其他硬币的可能性。

关于algorithm - 找零的方式数 N,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25657052/

相关文章:

使用 Dynamic Prog 的加泰罗尼亚数字

algorithm - 平衡多个参与者之间的集体开支

algorithm - Calculating a histogram on a streaming data - 在线直方图计算

c# - 文本与代码比率的良好算法?

查找另一点距离内所有点的算法

algorithm - 将 n 项排列在 k 个非空组中,使得每个组的最小元素和最大元素之间的差异最小

algorithm - 使用动态规划的可能楼梯

java - 使用动态规划的斐波那契数列

algorithm - 用于计算社区(互连节点)到另一个点之间的距离的有效算法

algorithm - 在数组中排列运算符,使得总和等于给定结果