Java 当订单很重要时,如何解决硬币兑换任务?

Java 当订单很重要时,如何解决硬币兑换任务?,java,algorithm,Java,Algorithm,正如我在 硬币兑换是指使用给定的一组面额d_1…d_m,找到对特定数量的美分,n进行兑换的方法的数量。这是整数分割的一般情况,可以用动态规划求解 这个问题通常被问到:如果我们想换N美分的硬币,而我们有无限量的S={S_1,S_2,…,S_m}值的硬币,我们可以用多少种方式来换(为了简单起见,顺序无关紧要。) 我试过这个,效果很好。因此,当不同硬币的顺序确实重要时,我如何修改它以找到所有可能的硬币组合 i、 e:以前 例如,对于N=4,S={1,2,3},有四个解:{1,1,1,1},{1,1,2

正如我在

硬币兑换是指使用给定的一组面额d_1…d_m,找到对特定数量的美分,n进行兑换的方法的数量。这是整数分割的一般情况,可以用动态规划求解

这个问题通常被问到:如果我们想换N美分的硬币,而我们有无限量的S={S_1,S_2,…,S_m}值的硬币,我们可以用多少种方式来换(为了简单起见,顺序无关紧要。)

我试过这个,效果很好。因此,当不同硬币的顺序确实重要时,我如何修改它以找到所有可能的硬币组合

i、 e:以前

例如,对于N=4,S={1,2,3},有四个解:{1,1,1,1},{1,1,2},{2,2},{1,3}

现在:

对于N=4,S={1,2,3},有7个解:{1,1,1,1},{1,1,2},{1,2,1},{2,1,1},{2,2},{1,3},{3,1}

在这里{1,1,1,1}即使可以按不同的顺序选择四个'1',也必须将其视为一个最终组合。而不是考虑到四枚硬币是不同的。因此,实际上,不同硬币的顺序必须不同,才能将其作为单独的组合来计算


例:{1,1,3}不会假定{1_a,1_b,3_a}是一个组合,{1_b,1_a,3_a}是另一个顺序不同的组合

如果你在参考的维基百科页面中提到“动态规划”算法,我认为你可以改变

table[ i, j ] = table[ i - S_j, j ] + table[ i, j - 1 ]

但我还不是100%确定。问题的关键是,在最初的问题中,当你检查硬币Sj时,你想在数量为i-Sj时加入可能的解决方案的数量,但只在硬币通过Sj时加入,这样你就不会得到之前序列的排列。通过将其更改为
表[i-S_j,m]
,您可以对排列进行计数


编辑:进一步研究后,我认为这是正确的,但与亨利的答案相当,后者要简单得多。此版本的问题(计算所有排列)不需要像原始数组那样将值存储在二维数组中。

如果您在参考的Wikipedia页面中提到“动态规划”算法,我认为您可以更改

table[ i, j ] = table[ i - S_j, j ] + table[ i, j - 1 ]

但我还不是100%确定。问题的关键是,在最初的问题中,当你检查硬币Sj时,你想在数量为i-Sj时加入可能的解决方案的数量,但只在硬币通过Sj时加入,这样你就不会得到之前序列的排列。通过将其更改为
表[i-S_j,m]
,您可以对排列进行计数


编辑:进一步研究后,我认为这是正确的,但与亨利的答案相当,后者要简单得多。此版本的问题(计算所有置换)不需要像原始数组那样将值存储在二维数组中。

仅计算解的数量比全部枚举要省力得多

让我们以S={1,2,3}为例,调用f(n)数量n的解的数量

然后我们有:

如果n<0,则f(n)=0

f(0)=1

f(n)=f(n-1)+f(n-2)+f(n-3)如果n>0(其中数字1,2,3是S的元素)

编写执行这些计算的程序并不太困难。你可以从低数字开始,然后逐步向上:

f(0) = 1
f(1) = 1
f(2) = 2
f(3) = 4
f(4) = 7
f(5) = 13
...
对于这个特殊的S,每个数字都是前面三个数字的和


如何得出这个公式?我再次以特定的集合S={1,2,3}为例,一般情况同样简单。要计算n的解决方案数,请查看第一个元素。它可以是1、2或3。如果为1,则有f(n-1)种方式来排列剩余的元素。如果为2,则剩余元素有f(n-2)种方式,最后如果为3,则剩余元素有f(n-3)种方式。因此,总数必须是三个解的总和。

仅计算解的数量比全部枚举要省力得多

让我们以S={1,2,3}为例,调用f(n)数量n的解的数量

然后我们有:

如果n<0,则f(n)=0

f(0)=1

f(n)=f(n-1)+f(n-2)+f(n-3)如果n>0(其中数字1,2,3是S的元素)

编写执行这些计算的程序并不太困难。你可以从低数字开始,然后逐步向上:

f(0) = 1
f(1) = 1
f(2) = 2
f(3) = 4
f(4) = 7
f(5) = 13
...
对于这个特殊的S,每个数字都是前面三个数字的和


如何得出这个公式?我再次以特定的集合S={1,2,3}为例,一般情况同样简单。要计算n的解决方案数,请查看第一个元素。它可以是1、2或3。如果为1,则有f(n-1)种方式来排列剩余的元素。如果为2,则剩余元素有f(n-2)种方式,最后如果为3,则剩余元素有f(n-3)种方式。因此,总数必须是三者之和。

当前的递归实现非常简单。它只传递剩余值和可能面额的索引。如果在n==0时传递了一个面额数组,则可以添加另一个检查以查看是否已经有了该组合。如果返回0,则返回1

这是一个动态的解决方案,需要比其他解决方案多得多的内存,但它会为您找到答案

func count(n, m, p[])
//regular if checks with additional nested if in (n == 0)
return count( n, m - 1, p[] ) + count( n - S[m], 0, p[] + S[m] )
在这个伪代码中,p[]+S[m]只意味着将S[m]添加到p[]中的下一个可用位置

编辑:

忘了加上当你俯冲时需要重置m

// n is remaining value
// m is index of S array
// p[] is array of coins used
// solutions[] is an array of p[] arrays
func count( n, m, p[]) {
  if n == 0
    if (p[] not in solutions[]){
      solutions[].add(p[])
      return 1
    }else{
      return 0
    }
  if n < 0
    return 0
  if m <= 0 and n >= 1
    return 0
  return count(n, m - 1, p[]) + count( n - S[m], 0, p[].add(S[m]))
}
//n是剩余值
//m是S数组的索引
//p[]是使用的硬币数组
//solutions[]是p[]数组的数组
函数计数(n,m,p[]{
如果n==0
if(p[]不在解决方案[]中){
解决方案[]。添加(p[])
返回1
}否则{