硬币变化(动态编程)
Posted
技术标签:
【中文标题】硬币变化(动态编程)【英文标题】:Coin Change (Dynamic Programming) 【发布时间】:2012-10-25 18:50:09 【问题描述】:对于硬币找零问题,我们通常有以下递推关系:
(P
是我们需要找零的总金额,d_i
是可用硬币)
但我们不能这样:
(V
是给定的可用硬币排序集,i
和 j
是它的下标,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
,所以这只是浪费内存
【讨论】:
以上是关于硬币变化(动态编程)的主要内容,如果未能解决你的问题,请参考以下文章