【问题标题】:Coin Change Algorithm - DP with 1D array硬币找零算法 - DP 与一维数组
【发布时间】:2015-11-19 19:57:18
【问题描述】:

我在这里遇到了硬币兑换问题的解决方案:Coin Change。在这里,我能够理解第一种递归方法,第二种方法使用 DP 和 2D 数组。但是我无法理解第三种解决方案背后的逻辑。

据我所知,最后一种方法适用于考虑硬币找零时使用的硬币顺序的问题。我对么?如果我错了,谁能解释我。

【问题讨论】:

  • “最后一种方法适用于考虑硬币更换中使用的硬币顺序的问题” - 不确定这意味着什么。能详细点吗?
  • 我在这里的意思是硬币的集合 (1, 2, 1) 被认为与 (1, 1, 2) 不同。这里的总和是相同的,但在计算时却被认为是不同的。
  • second line 说:“硬币的顺序无关紧要。”
  • 是的,这就是我的问题。当硬币的顺序无关紧要时,我无法理解为什么第三种方法有效并计算答案。
  • 算法的哪一部分让你觉得顺序很重要?

标签: dynamic-programming coin-change


【解决方案1】:

好吧,我自己想通了!

这可以使用归纳法轻松证明。令 table[k] 表示总共 k 的变化方式。现在该算法由两个循环组成,一个由 i 控制并遍历包含所有不同硬币的数组,另一个是 j 控制循环,对于给定的 i,更新数组表中元素的所有值。现在考虑对于一个固定的 i,我们已经计算了可以为从 1 到 n 的所有值给出变化的方式的数量,这些值存储在从 table[1] 到 table[n] 的表中。当 i 控制循环迭代 i+1 时,table[j] 中任意 j 的值会增加 table[j-S[i + 1]],这只不过是我们可以使用至少一个硬币创建 j 的方法value S[i + 1](存储硬币值的数组)。因此,table[j] 中的总价值等于我们可以使用价值 S[1]....S[i] 的硬币(之前已经存储)和价值 table[j-S[i + 1]]。这与递归算法中使用的问题的最优子结构相同。

【讨论】:

  • 你在解释中混合了一些指数,但我认为你明白了:i(行)代表小和,j 是指数 j 上的硬币S。单元格table[i][j] 表示总和为i 的硬币可能组合的数量,其中包括硬币S[j]。该表是自下而上构建的,这意味着在每次迭代中逐渐计算“子和”,而不是计算“递归调用”,而是从先前已经计算的子和中获取。这也是为什么我们完成最后一个硬币的迭代后,最终结果会出现在最后一行
  • 表格是一维的,table[k] 表示创建变化的方式的数量,总共 k。在第三个算法中,二维数组被折叠并覆盖一维数组,因为不再需要过去的数据。你的逻辑是对的。你能指出我在哪里混合了指数吗?我会纠正它们。
  • 只需在以下部分中将 i 与 j (和虎钳)交换:“当 i 控制循环迭代 i+1 时,table[j] 中任意 j 的值按 table 递增[j-S[i + 1]] 这不过是我们可以使用至少一个值为 S[i + 1] 的硬币(存储硬币值的数组)创建 j 的方法。因此 table[j] 中的总值等于我们可以用价值 S[1]..S[i](之前已经存储过)和价值表 [j-S[i + 1]]" 的硬币创建找零的方法的数量
【解决方案2】:
int arr[size];
memset(arr,0,sizeof(size));
int n;
cin>>n;
int sum;
cin>>sum;
int a[size];
fi(i,n)
cin>>a[i];
arr[0]=1;
fi(i,n)
for(int j=arr[i]; j<=n; j++)
    a[j]+=a[j-arr[i]];
cout<<arr[n];

数组arr被初始化为0,以表明i之和可以表示的方式数为零(即未初始化)。但是,可以表示 0 和的方式的数量是 1(零方式)。 此外,我们取出每个硬币并从硬币面额开始初始化数组中的每个位置。 a[j]+=a[j-arr[i]] 意味着我们基本上将表示和 j 的可能方式增加了前面所需的方式数量 (j-arr[i])。 最后我们输出a[n]

【讨论】:

  • 欣赏vaultah
猜你喜欢
  • 2012-08-05
  • 2016-01-25
  • 2013-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多