硬币变化(动态编程)

Posted

技术标签:

【中文标题】硬币变化(动态编程)【英文标题】:Coin Change (Dynamic Programming) 【发布时间】:2012-10-25 18:50:09 【问题描述】:

对于硬币找零问题,我们通常有以下递推关系: (P 是我们需要找零的总金额,d_i 是可用硬币)

但我们不能这样: (V 是给定的可用硬币排序集,ij 是它的下标,Vj 是给定的最高价值硬币)

C[p,Vi,j] = C[p,Vi,j-1]     if Vj > p
          = C[p-Vj,Vi,j] + 1  if Vj <=p

我写的有什么问题吗?虽然解决方案不是动态的,但它不是更有效吗?

【问题讨论】:

这不是假设 V 将包含一个价值 1 个单位的硬币。如果 P = 7 和 V = [3, 2],你最终会得到 2 个价值 3 个硬币,然后出错而不是 1 个价值 3 个硬币和 2 个价值 2 个硬币。 @LastCoder 我明白你的意思。上述解决方案假设我们有一枚价值 1 单位的硬币。现在接下来的事情是,如果给我们一个价值 1 个单位的硬币,那么上面的解决方案比动态解决方案更有效,对吧? 您在公式中哪里使用Vi @IVlad:这个集合实际上是 Vi 到 Vj。所以当我写 Vi,j 时,我假设集合 V 包含从 Vi 到 Vj 的所有元素。当我写 Vi,j-1 时,我假设集合 V 包含从 Vi 到 Vj-1 的所有元素,这意味着最后一个硬币被排除在硬币集合之外。 这是一个非常令人困惑的符号,因为您也只使用Vj,并且使用逗号分隔索引和函数参数。我建议使用方括号使其更清晰,我将您的公式读为C[p,(Vi),(j-1)]; C[(p-Vj),(Vi),(j)] 【参考方案1】:

考虑P = 6, V = 4, 3, 1。你会选择4, 1, 1而不是3, 3,所以3硬币而不是最佳2

【讨论】:

【参考方案2】:

您编写的内容类似于仅在特定条件下有效的贪心算法。 (见-How to tell if greedy algorithm suffices for finding minimum coin change?)。

另外,在您的版本中,您实际上并没有在循环中使用Vi,所以这只是浪费内存

【讨论】:

以上是关于硬币变化(动态编程)的主要内容,如果未能解决你的问题,请参考以下文章

动态硬币变化算法(最佳结果)

硬币找零(动态编程)

硬币交换变体的动态编程

每日编程-20170327

算法-硬币排成线II(动态规划)

硬币找零问题之动态规划