Algorithm 更改金额N的方法数

Algorithm 更改金额N的方法数,algorithm,dynamic-programming,Algorithm,Dynamic Programming,我遇到了这个问题: 给定一个值N,如果我们想换N美分,并且我们有无限量的S={S1,S2,…,Sm}值的硬币,我们可以用多少种方式来换?硬币的顺序无关紧要 例如,对于N=4和S={1,2,3},有四种解决方案:{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 我想出了解决办法: // recurrence relati

我遇到了这个问题:

给定一个值N,如果我们想换N美分,并且我们有无限量的S={S1,S2,…,Sm}值的硬币,我们可以用多少种方式来换?硬币的顺序无关紧要

例如,对于N=4和S={1,2,3},有四种解决方案:{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

我想出了解决办法:

// 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];
}
//递归关系
count[N]=所有面额的count[N-d]让
C(i,j)
使用面额为
S1,…,Sj的硬币来计算总
i
的方法的数量。您的代码实现了以下循环(有序方式)

C(i,m)| i<0=0
|i==0=1
|i>0=sum_{j=1}^mc(i-Sj,m)
链接代码实现了不同的重复(无序方式)

C(i,j)| i<0=0
|i==0=1
|i>0&&j0&&j>0=C(i-Sj,j)+C(i,j-1)
这两个代码之间的差异很微妙:或多或少只是循环的嵌套方式。在转到
i+1
之前,您添加了
i
的所有术语,但是链接的代码为每个
i
添加了
j
术语,然后为每个
i
添加了
j+1
术语,以此类推,当链接代码考虑使用小计
i
中的面值-Sj
硬币的可能性时,它隐含地只考虑继续使用面值
S1,…,Sj
硬币的那些解决方案,因为
i-Sj
的当前总数不包括使用其他硬币的可能性

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)