常用算法之貪心算法


一、什么是貪心算法?

貪心算法指對問題求解時,總是做出在當前看來是最好的選擇,期望通過所做的局部最后選擇來產生出一個全局最優解。

二、貪心算法的適用場景

首先,在利用貪心算法求解問題之前,我們需要清楚什么樣的問題適合用貪心算法求解。一般而言,能夠利用貪心算法求解的問題都會具備以下兩點性質:

  1. 貪心選擇
  2. 最優子結構。
    如果我們能夠證明問題具備這兩個性質,那么就可以設計出它的一個貪心算法。
2.1 貪心選擇性質

一個全局最優解可以通過可以通過局部最優選擇來達到。
換句話說,當考慮如何做選擇時,我們只考慮對當前問題最佳的選擇、而不考慮子問題的結果。
在貪心算法中,我們所做的總是當前看似最佳的選擇,然后再解決選擇之后所出現的子問題。貪心算法所做的當前選擇可能要依賴於已經做出的所有選擇,但不依賴於有待於做出的選擇或子問題的解。
我們必須證明在每一步所做的貪心選擇最終能產生一個全局最優解。

2.2 最優子結構

對於一個問題來說,如果它的一個最優解包含了其子問題的最優解,則稱該問題具有最優子結構。
假設在原問題中做了一個貪心選擇而得到了一個子問題,真正要做的是證明將此問題的最優解與所做的貪心選擇合並后,的確可以得到原問題的一個最優解。這個方案意味着要對子問題采用歸納法,來證明每個步驟中所做的貪心選擇最終會產生出一個最優解。

貪心算法與動態規划的不同在於他對每個子問題的解決方案都是局部最優選擇,不能回退。
動態規划則會保存以前的運算結果,並根據以前的結果對當前進行選擇,有回退功能。

如何證明貪心算法的正確性?

以活動選擇問題為例, 活動集合S={1,2,..., n}。

現在要證明的是,如果每一步都進行貪心選擇,執行到第k步時,選擇的k項活動為i1, i2, ..., ik,那么存在一個最優解包含活動i1,i2, ... ik。根據上述命題,對於任何k,算法前k步的選擇都將導致最優解,至多到第n步將得到問題實例的最優解。

  • 采用歸納法證明:
    首先將活動按照結束時間非遞減排序,記排序后的結果為S={1,2,...,n}, f1<=f2<=...<=fn。
  1. 當k = 1時,設最優解為A = {i1, i2, ... , ij}, 如果i1不等於1, 因為活動1結束的時間最早,那么用1替換i1后得到的A'也是問題的一個最優解;
  2. 假設對於任意的正整數k,命題正確, 即存在一個全局最優解A={i1=1, i2, ..., ik}∪B,其中B為全局最優解A中除了i1, i2,...,ik以外的部分。
    記S中除了{i1, i2, ..., ik}剩下部分中與i1, i2, ..., ik相容的活動集合為S', 那么B必然是S'的一個最優解。
    反證法證之:
    假設B不是S'的最優解,即存在最優解B'的活動比B多, 那么{i1, i2,...,ik}∪B' > {i1,i2,...,ik}∪B, 與A是全局最優解矛盾。
    既然B是S'的一個最優解。根據1的結論,S'中結束時間最早的活動(ik+1)總會導致一個最優解,如果B中包含ik+1, 那么就說明最優解A中包含ik+1;
    如果B中不包含ik+1, 那么一定存在S'的另外一個最優解B'包含ik+1, 即:
    {i1,i2,...,ik}∪B = {i1,i2,...,ik}∪B', 其中B'={ik+1,...}
    因此{i1, i2,...,ik, ik+1}一定出現在一個最優解集合中。
    命題得證。


免責聲明!

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



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