某種 找換硬幣問題的貪心算法的正確性證明


一,問題介紹

最近一直在看貪心算法的正確性證明(如何證明貪心算法獲得的解一定是最優解),感覺“剪枝”技巧用得比較多。再看了下《算法導論》中貪心算法一章里面的一個練習---找換硬幣問題。這個問題對於某些 面值的硬幣 是有最優解的,故記錄下其中的一些證明思路。

考慮用最少的硬幣數 來找 n 分錢的問題,假設每個硬幣的值都是整數。

如果可換的硬幣的單位是 c 的冪,也就是 c0,c1,... ,ck ,其中整數 c>1,k>=1

證明貪心算法總可以產生一個最優解。

 

二,找換硬幣的貪心策略

這里的貪心策略很容易想到:總是優先選擇 大面值的硬幣 去找。比如,現有 1分、5分、25分的硬幣可用來找錢,現在我們需要找 n=32分 的零錢,如何找?

優先選擇大面值的嘛,那就是先選 25分;選完之后,還要找32-25=7,那就再選5分的,最終再先2個1分的。即可。

這里:32=25+5+1+1,一共用了4枚硬幣。那么,問題來了!!!還有沒有其他策略 只需要 3 枚硬幣?或者更少的硬幣?

這就需要證明貪心策略 有沒有 最優解了?對於這個問題而言,如果用來找換的硬幣的 面值 滿足某種性質,該貪心策略是有最優解的。

這里說的某種性質就是:可換的硬幣的單位(或者稱 面值)是 c 的冪,也就是 c0,c1,... ,ck ,其中整數 c>1,k>=1

下面給出正確性證明。

這里需要強調一點: 硬幣面值滿足上面的性質時貪心算法一定能產生最優解,但是不滿足時,也有可能有最優解。比如,面值為1,5,10,20,50,100時,貪心找零也一定有最優解。

 

三,找換硬幣的貪心算法的正確性證明

在進行證明之前,先提一個性質:對於最優解而言,如果使用了面值為 ci 的硬幣去找零,那么 ci 最多只能使用 c-1 個。

因為我們的目標是使用 最少數目的硬幣,對於最優解而言,如果使用了面值為 ci 的硬幣去找零,那么 ci 最多只能使用 c-1 個。

why? 假設使用了 c 個(大於c個也一樣)面值為 ci 的硬幣去找零,那我為什么不用一個 面值為 ci+1 的硬幣去找呢?

這樣,我就可以用更少的硬幣數啊(c>1)。所以說,在最優解里面,如果使用了面值為 ci 的硬幣去找零,那么 面值為ci 的硬幣 最多只能使用 c-1 個。

OK,下面再次用到剪枝的思想來證明貪心選擇的正確性了。

總體思路是:先考察一個最優解,然后證明可對該解進行修改,使其采用貪心選擇,這個選擇將原問題變成一個相似的、但是“更小”的問題。(這里說的“更小”是一種抽象,並不是具體意義上的更小)

k 是可找換的硬幣的種類數,n 是需要找換的價值,a(i)表示使用多少個 面值為 ci 的硬幣。假設硬幣已經按面值從小到大排序。

對於貪心選擇而言,我們一定會選擇面值為 c^j 的硬幣,因為:我們的貪心策略就是總是優先選擇 面值最大的硬幣。

我們的目標是證明,對於所有的貪心選擇而言,它們都不可能產生最優解。

對於非貪心選擇,是不會選擇 面值為 c^j (or higher)的硬幣的。非貪心選擇使用的硬幣如下:

其中,a(i)表示使用了 a(i)個 面值為 ci 的硬幣,總數之和是n。別忘了,n 就是需要找零的數目

而對於貪心選擇而言,如果面值為 c^j 的硬幣可用(當 n>=c^j 時),我們是優先使用 面值為 c^j 的硬幣的。

因此有:

這說明,在面值為 c^j 的硬幣 可用的情況下,換句話說:在 c^j <=n 的情況下,貪心選擇沒有使用 c^j 嘛。(選擇了的話,那就是貪心選擇了嘛...~)

 這里就會有矛盾了,根據前面提到的性質:有, a(i) <= c-1

 

 

從而,證明了貪心選擇的正確性。

再來理解下它:總體思路是:先考察一個最優解,然后證明可對該解進行修改,使其采用貪心選擇,這個選擇將原問題變成一個相似的、但是“更小”的問題。(這里說的“更小”是一種抽象,並不是具體意義上的更小)

這里的最優解是:非貪心選擇下的某個最優解,然后剪枝:將非貪心選擇下的某個元素去掉,然后添入貪心選擇的那個元素。其實就是下面的這個公式。

              從而得到了一個更優的問題。

 

四,參考資料

部分背包問題的貪心算法正確性證明

某種 找換硬幣問題的貪心算法的正確性證明

從 活動選擇問題 看動態規划和貪心算法的區別與聯系

找換硬幣問題的求解 以及與 0-1背包問題區別

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM