为什么贪婪的硬币兑换算法不适用于某些硬币集?


70

我了解用于硬币找零问题的贪婪算法(如何用尽可能少的硬币数目支付一定的金额)如何工作-它总是选择面额最大的硬币而不超过剩余金额-并且总是能找到正确的解决方案特定的硬币套。

但是对于某些硬币集,贪婪算法的总和会失败。例如,对于集合{1, 15, 25}和总和30,贪婪算法首先选择25,剩下的余数为5,然后选择5个1表示总共6个硬币。但是,使用最少数量的硬币的解决方案是选择15次两次。

一组硬币必须满足什么条件,以便贪婪算法找到所有和的最小解?


3
答案很大程度上取决于算法的作用:很容易对硬币感到贪婪,您应该告诉我们算法的作用以及其作用方式。
谢尔盖·卡利尼琴科

2
...该算法应解决的实际问题是什么?
user541686

1
好的,我想我没有问正确的问题。为了使算法不起作用,一组面额的内容必须正确。例如 从(25,15,1)贪婪中赚取30美分,我们得到25,1,1,1,1,1,但15 15更好。25 15和1会使贪婪无效呢?

2
@j_random_hacker可以从OP的注释中推断出,但不能从问题中推断出来。该问题本身没有暗示该算法应该做什么,因此这不是一个好问题。
丹尼尔·菲舍尔

1
我一直在寻找类似的问题..为什么贪婪的硬币找零算法对某些硬币集有效?因此,有一篇论文对贪婪解成为最佳解的充分条件给出了非常丑陋的表述。相信我,你不想读:-)
Rohit

Answers:


23

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

  1. S是一个有限的非空集
  2. l是S的一个非空子集,称为独立子集,因此,如果B-> l并且A是B的子集,则A-​​> l
  3. 如果A-> l,B-> l和| A | <| B |,那么有一些元素x-> BA使得AU {x}-> l

在我们的硬币更换问题中,S是按降序排列的所有硬币的集合。我们需要通过S中最少的硬币个数来获得V的值

在我们的例子中,l是一个包含所有子集的独立集合,因此对于每个子集,以下内容均成立:它们中的值之和为<= V

如果我们的集合是拟阵,那么我们的答案是l中的最大集合A,其中不能再添加x

为了进行检查,我们看一下拟阵的属性是否在集合S = {25,15,1}中成立,其中V = 30现在,l中有两个子集:A = {25}和B = {15,15} | A | <| B |,那么有一些元素x-> BA使得AU {x}-> l(根据3)因此,{25,15}应该属于l,但这是自25 + 15> 30以来的矛盾

因此,S不是拟阵,因此贪婪方法对它无效。


12
这个说法是不正确的。如果S = {25,10,5,1},V = 30,A = {25},B = {10,10,10},则同一个参数表明{S,I}不是拟阵,因为{ 25、10)不在I中。另一方面,贪婪算法适用于S的选择(如CLRS问题16-1a中所示)。特定拟阵结构的存在是贪婪算法正确性的充分但非必要条件。
Tobias Hagge'Feb 17'15

@TobiasHagge我们是否有一个条件告诉我们贪婪算法将失败一组?
dh16

13

在任何情况下,如果没有硬币的价值加到最低面额的硬币都比面额的两倍小,且硬币的面额立即小于硬币的面额,贪婪算法就会起作用。

即{1,2,3}之所以起作用是因为[1,3]和[2,2]相加相同的值,但是{1,15,25}不起作用是因为(对于更改30)15 + 15> 25 +1


1
好答案。这就是我想要的东西:)
Adam Van Oijen

1
通过测试可确保贪婪方法有效,但事实并非如此。贪婪适用于{1,5,15,25}。
lhhong

9
这个答案似乎是错误的。贪婪算法没有给出硬币{1,图8,20}和24目标值的最佳解决方案,即使8 + 8 = 16 <21 = 20 + 1
亚历Yursha

4

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

测试很简单:对于`1 <= k <= 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。所以,我们知道,贪婪在{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的硬币。最后,使用这5个面额中的任何一个{64、32、16、8、4、2、1}的子集,不能排除'1'并且满足贪婪,也将导致最多8个硬币。因此,存在线性权衡。将面额数量从5增加到7会减少表示1到100之间的任何值所需的最大硬币数量从8减少到6。

另一方面,如果您想最大程度地减少买卖双方之间交换的硬币数量,假设它们各自的口袋中每种面额至少有一个硬币,那么这个问题就等于平衡任何硬币所需的重量最少。重量从1到N磅。事实证明,如果以3的幂给出硬币面额,则购买中交换的硬币数量最少。{1, 3, 9, 27, . . .}

参见/puzzling/186/whats-the-fewest-weights-you-need-to-balance-any-weight-from-1-to-40-pounds



1

今天,我在Codeforces上解决了与此类似的问题(链接将在最后提供)。我的结论是,要使硬币找零问题能够由Greedy alogrithm解决,它应满足以下条件:

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


-3

一个容易记住的情况是,任何一组硬币,如果它们按升序排序并且您具有:

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

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

根据您查询的范围,可能会有更好的分配(根据所需硬币的数量)。例如,如果您正在考虑范围(6..8),并且您使用硬币<6,7,8>而不是<1,2,4,8>。

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

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


这是一个有趣的链接,但是所有事实证明,如果一组最大硬币m的硬币不是贪心的,那么必须有一个总和<= 2m,贪心和最优解可以得出不同数量的硬币。(也就是说,仅查看少量金额就可以发现“非贪婪”是很明显的。)也许有一种方法可以证明,在每组贪婪的硬币中,每枚硬币必须> =下一枚硬币的2倍,最大,但我看不到。
j_random_hacker 2012年

2
除了您的链接证明与您声明的内容不同之外,您声明的内容也证明是错误的:硬币组{ 25, 10, 1 }符合“至少是先前硬币的两倍”的条件,但对于总共30个,贪婪算法将得出25+ 5 * 1(6个硬币),而最佳解决方案是3 * 10(3个硬币)。-1。
j_random_hacker 2012年

贪婪算法确实提供了有效答案(25 + 1 + 1 + 1 + 1 + 1),但这并不是最有效的。
2013年

OP的问题清楚地表明,他/他打算将“作品”表示为“使用最少数量的硬币”。(顺便说一句,如果您要求硬币组包含1美分硬币,那么选择不会导致总数超过目标数量的硬币的任何方法都将以您的较低标准“起作用”,即“使用任何数量”,因此贪婪无济于事。)
j_random_hacker 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.