为什么贪婪的硬币改变算法不适用于某些硬币组?

时间:2012-11-26 02:42:29

标签: algorithm greedy

我理解硬币改变问题的贪婪算法(用尽可能少的硬币支付特定金额)是如何工作的 - 它总是选择具有最大面额但不超过剩余金额的硬币 - 并且它总是找到特定硬币套装的正确解决方案。

但对于某些硬币集,有贪婪算法失败的总和。例如,对于集合{1, 15, 25}和总和30,贪心算法首先选择25,剩余5,然后五个1,总共六个硬币。但是硬币数量最少的解决方案是选择15次。

一组硬币必须满足哪些条件才能使贪婪算法找到所有总和的最小解?

7 个答案:

答案 0 :(得分:18)

形成拟阵(https://en.wikipedia.org/wiki/Matroid)的集合可以通过使用贪婪方法来解决硬币变化问题。简而言之,拟阵是一对有序的 M =(S,l)满足以下条件:

  1. S是有限非空集
  2. l是S的子集的非空子族,称为独立子集,如果B-> l A是B的子集,然后是A - >升
  3. 如果A-> l,B-> l和| A | < | B |,然后有一些元素x-> B-A使得A U {x} - > l
  4. 在我们的硬币更换问题中,S是一组递减值的所有硬币 我们需要通过S

    中的最小硬币数量来获得V值

    在我们的例子中,l是一个独立的集合,包含所有子集,以便每个子集都包含以下内容:它们中的值的总和为< = V

    如果我们的集合是一个matroid,那么我们的答案是l中的最大集合A,其中没有x可以进一步添加

    要检查,我们看看拟阵中的属性是否保持在集合S = {25,15,1}其中V = 30 现在,l中有两个子集: A = {25}且B = {15,15} 自| A | < | B |,然后有一些元素x-> B-A使得A U {x} - > l(根据3) 因此,{25,15}应该属于l,但是自25 + 15> 30

    以来它是矛盾的

    所以,S不是一个拟阵,因此贪婪的方法不适用于它。

答案 1 :(得分:7)

在任何没有硬币的情况下,当加到最低面额时,它的值低于直接小于它的面额的两倍,贪婪算法就可以工作。

即。 {1,2,3}有效,因为[1,3]和[2,2]增加了相同的值       但是{1,15,25}不起作用,因为(对于变化30)15 + 15> 25 + 1

答案 2 :(得分:4)

这是一个复发问题。给定一组硬币{Cn, Cn-1, . . ., 1},使得对于1 <= k <= n, Ck > Ck-1,如果Ck> 1,则贪婪算法将产生最小数量的硬币。 Ck-1 + Ck-2和值V=(Ck + Ck-1) - 1,将贪婪算法应用于硬币子集{Ck, Ck-1, . . ., 1},其中Ck <= V导致硬币数量少于应用贪婪算法到硬币子集{Ck-1, Ck-2, . . ., 1}

测试很简单:对于`1&lt; = k&lt; = n测试贪婪算法产生的Ck + Ck-1 - 1的硬币数量。对硬币组{Ck,Ck-执行此操作1 ,. 。 。,1}和{Ck-1,Ck-2 ,. 。 。,1}。如果对于任何k,后者产生的硬币比前者少,则贪心算法将不适用于该硬币集。

例如,当n = 4时,考虑硬币集{C4,C3,C2,1} = {50,25,10,1}。以k = n = 4开始,然后V = Cn + Cn-1 -1 = 50 + 25-1 = 74作为测试值。对于V = 74,G {50,25,10,1} = 7个硬币。 G {25,10,1} = 8个硬币。到现在为止还挺好。现在让k = 3。然后V = 25 + 10-1 = 34。 G {25,10,1} = 10个硬币,但G {10,1} = 7个硬币。因此,我们知道贪婪算法不会最小化硬币组的硬币数量{50,25,10,1}。另一方面,如果我们在这个硬币组中添加一个镍币,则G {25,10,5,1} = 6且G {10,5,1} = 7.同样,对于V = 10 + 5-1 = 14,我们得到G {10,5,1} = 5,但G {5,1} = 6.所以,我们知道,Greedy适用于{50,25,10,5,1}。

这引出了一个问题:什么应该是硬币的面额,满足贪婪算法,这导致从1到100的任何值的最小最坏情况数量的硬币?答案非常简单:100个硬币,每个硬币具有1到100的不同值。可以说这不是很有用,因为它可以在每次交易时线性搜索硬币。更不用说铸造这么多不同面额并跟踪它们的费用。

现在,如果我们想要主要减少面额的数量,同时最小化由Greedy生产的1到100的任何值的硬币结果数量,那么硬币的面额为2:{64,32,16, 8,4,2,1}对于任何值1:100(7位数中最大1的值,其值小于十进制100),最多产生6个硬币。但这需要7种面额的硬币。五种面额{50,25,10,5,1}的最坏情况是8,其发生在V = 94和V = 99。权力为3 {1,3,9,27,81}的硬币也只需要5个面额可供贪婪服务,但也会产生8个硬币的最差情况,值为62和80.最后,使用任何五个面额{64,32,16,8,4,2,1}的子集不能排除'1',并且满足Greedy,也会产生最多8个硬币。所以有一个线性的权衡。将面额数从5增加到7会减少从8到6分别代表1到100之间的任何值所需的最大硬币数。

另一方面,如果你想最大限度地减少买家和卖家之间交换的硬币数量,假设每个硬币的口袋中至少有一个硬币,那么这个问题就是相当于平衡1到N磅的任何重量所需的最小重量。事实证明,如果硬币面额的权力为3:{1, 3, 9, 27, . . .},则购买时交换的硬币数量最少。

请参阅https://puzzling.stackexchange.com/questions/186/whats-the-fewest-weights-you-need-to-balance-any-weight-from-1-to-40-pounds

答案 3 :(得分:1)

今天,我在Codeforces上解决了与此类似的问题(链接将在最后提供)。 我的结论是,要使贪婪的硬币硬币兑换问题得到解决,它应符合以下条件:-

1。按升序对硬币值进行排序时,大于当前元素的所有值都应被当前元素整除。

例如硬币= {1,5,10,20,100},这将给出正确的答案,因为{5,10,20,100}都可以被1,{10,20,100}都可以除以5,{20,100 }全部可被10整除,{100}全部可被20整除。

希望这给出了一些想法。

996 A-打彩票 https://codeforces.com/blog/entry/60217

答案 4 :(得分:1)

好吧,我们真的需要重新表述这个问题……贪婪算法的本质是尝试使用提供的硬币面额来获得目标值。您对贪婪算法所做的任何更改只会改变达到目标值的方式。 它不考虑使用的最低代币...... 为了更好地解决这个问题,不存在安全的举措。 更高面额的硬币可能会很快产生目标价值,但这不是一个安全的举动。 示例 {50,47,51,2,9} 获得 100 贪婪的选择是拿最高面额的硬币更快地达到 100。 51+47+2 好吧,它达到了,但 50+50 应该可以..

让 {50,47,51,9} 得到 100 如果它贪婪地选择最高的硬币 51 它需要从集合 49。它不知道是否可能。它试图达到 100 但它不能 而改变贪婪的选择只会改变达到100的方式 这些类型的问题产生了一组解决方案和决策树分支的形式。

答案 5 :(得分:0)

如果贪婪算法给出的硬币数量对于所有金额都是最佳的,则硬币系统是规范的。

This paper offers an O(n^3) algorithm for deciding whether a coin system is canonical, where n is the number of different kinds of coins.

对于非规范硬币系统,有一个量c,贪婪算法产生次优数量的硬币; c被称为反例。如果最小的反例大于最大的单个硬币,则硬币系统是紧的。

答案 6 :(得分:-3)

一个容易记住的案例是任何一组硬币,如果它们按升序排序并且你有:

coin[0] = 1
coin[i+1] >= 2 * coin[i], for all i = 0 .. N-1 in coin[N]

然后使用这种硬币的贪婪算法将起作用。

根据您查询的范围,可能会有更优化(就所需硬币数量而言)分配。例如,如果您正在考虑范围(6..8)并且您有硬币&lt; 6,7,8&gt;而不是&lt; 1,2,4,8&gt;。

在N +上完成的最有效的硬币分配与上述规则相同,为您提供硬币1,2,4,8 ......;它只是任何数字的二进制表示。从某种意义上说,基础之间的对话本身就是一种贪婪的算法。

Max Rabkin在本次讨论中提供了关于&gt; = 2N不等式的证明: http://olympiad.cs.uct.ac.za/old/camp0_2008/day1_camp0_2008_discussions.pdf