貪心演算法講解

2021-07-03 17:59:09 字數 4065 閱讀 1848

以下參照一張清華ppt課件

1.定義概覽

貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的僅是在某種意義上的區域性最優解。貪心演算法不是對所有問題都能得到整體最優解,但對範圍相當廣泛的許多問題他能產生整體最優解或者是整體最優解的近似解。

貪心演算法在有最優子結構的問題中尤為有效。最優子結構的意思是區域性最優解能決定全域性最優解。簡單地說,問題能夠分解成子問題來解決,子問題的最優解能遞推到最終問題的最優解

演算法思想:從問題的某乙個初始解出發逐步逼近給定的目標,以盡可能快的地求得更好的解。當達到某演算法中的某一步不能再繼續前進時,演算法停止。

該演算法存在問題:

1). 不能保證求得的最後解是最佳的;

2). 不能用來求最大或最小解問題;

3). 只能求滿足某些約束條件的可行解的範圍。

dijkstra演算法、prim演算法和kruskal演算法都屬於典型的貪心演算法

2.活動安排問題

設有n個活動的集合e=,其中每個活動都要求使用同一資源,如演講會場等,而在同一時間內只有乙個活動能使用這一資源。每個活動i都有乙個要求使用該資源的起始時間si和乙個結束時間fi,且si 。如果選擇了活動i,則它在半開時間區間[si, fi)內占用資源。若區間[si, fi)與區間[sj, fj)不相交,則稱活動i與活動j是相容的。也就是說,當si≥fj或sj≥fi時,活動i與活動j相容。 

在下面所給出的解活動安排問題的貪心演算法greedyselector :

int greedyselector(int s[maxnum] , int f[maxnum], bool a)  //

s陣列記錄著相應活動開始時間,f陣列記錄著相應活動結束時間

else

a[i]=false; //

與已安排活動不相容,標記此活動未安排

}

return

count;

}

由於輸入的活動以其完成時間的非減序排列,所以演算法greedyselector每次總是選擇具有最早完成時間的相容活動加入集合a中。直觀上,按這種方法選擇相容活動為未安排活動留下盡可能多的時間。也就是說,該演算法的貪心選擇的意義是使剩餘的可安排時間段極大化,以便安排盡可能多的相容活動。

演算法greedyselector的效率極高。當輸入的活動已按結束時間的非減序排列,演算法只需o(n)的時間安排n個活動,使最多的活動能相容地使用公共資源。如果所給出的活動未按非減序排列,可以用o(nlogn)的時間重排。

例:設待安排的11個活動的開始時間和結束時間按結束時間的非減序排列如下:

演算法greedyselector 的計算過程如左圖所示。圖中每行相應於演算法的一次迭代。陰影長條表示的活動是已選入集合a的活動,而空白長條表示的活動是當前正在檢查相容性的活動。

若被檢查的活動i的開始時間si小於最近選擇的活動j的結束時間fi,則不選擇活動i,否則選擇活動i加入集合a中。

貪心演算法並不總能求得問題的整體最優解。但對於活動安排問題,貪心演算法greedyselector卻總能求得的整體最優解,即它最終所確定的相容活動集合a的規模最大。這個結論可以用數學歸納法證明。

3.貪心演算法基本要素

1).貪心選擇性質

貪心選擇性質是指所求問題的整體最優解可以通過一系列區域性最優的選擇,即貪心選擇來達到。這是貪心演算法可行的第乙個基本要素,也是貪心演算法與動態規劃演算法的主要區別。

在動態規劃演算法中,每步所作的選擇往往依賴於相關子問題的解。因而只有在解出相關子問題後,才能作出選擇。而在貪心演算法中,僅在當前狀態下作出最好選擇,即區域性最優選擇。然後再去解作出這個選擇後產生的相應的子問題。貪心演算法所作的貪心選擇可以依賴於以往所作過的選擇,但決不依賴於將來所作的選擇,也不依賴於子問題的解。正是由於這種差別,動態規劃演算法通常以自底向上的方式解各子問題,而貪心演算法則通常以自頂向下的方式進行,以迭代的方式作出相繼的貪心選擇,每作一次貪心選擇就將所求問題簡化為乙個規模更小的子問題。

對於乙個具體問題,要確定它是否具有貪心選擇性質,我們必須證明每一步所作的貪心選擇最終導致問題的乙個整體最優解。通常可以用我們在證明活動安排問題的貪心選擇性質時所採用的方法來證明。首先考察問題的乙個整體最優解,並證明可修改這個最優解,使其以貪心選擇開始。而且作了貪心選擇後,原問題簡化為乙個規模更小的類似子問題。然後,用數學歸納法證明,通過每一步作貪心選擇,最終可得到問題的乙個整體最優解。其中,證明貪心選擇後的問題簡化為規模更小的類似子問題的關鍵在於利用該問題的最優子結構性質。

2).最優子結構性質

當乙個問題的最優解包含著它的子問題的最優解時,稱此問題具有最優子結構性質。問題所具有的這個性質是該問題可用動態規劃演算法或貪心演算法求解的乙個關鍵特徵。在活動安排問題中,其最優子結構性質表現為:若a是對於正的活動安排問題包含活動1的乙個最優解,則相容活動集合a』=a—是對於e』=的活動安排問題的乙個最優解。

3).貪心演算法與動態規劃演算法的差異

貪心演算法和動態規劃演算法都要求問題具有最優子結構性質,這是兩類演算法的乙個共同點。大多數時候,能用貪心演算法求解的問題,都可以用動態規劃演算法求解。但是能用動態規劃求解的,不一定能用貪心演算法進行求解。

4.0-1揹包問題和揹包問題

1).兩個問題的描述

給定n種物品和乙個揹包。物品i的重量是wi,其價值為vi,揹包的容量為c。應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?

在選擇裝入揹包的物品時,對每種物品i只有2種選擇,即裝入揹包或不裝入揹包。不能將物品i裝入揹包多次,也不能只裝入部分的物品i。

與0-1揹包問題類似,所不同的是在選擇物品i裝入揹包時,可以選擇物品i的一部分,而不一定要全部裝入揹包,1≤i≤n。

這2類問題都具有最優子結構性質,極為相似,但揹包問題可以用貪心演算法求解,而0-1揹包問題卻不能用貪心演算法求解。

2).用貪心演算法解揹包問題的基本步驟:

首先計算每種物品單位重量的價值vi/wi

,然後,依貪心選擇策略,將盡可能多的單位重量價值最高的物品裝入揹包。若將這種物品全部裝入揹包後,揹包內的物品總重量未超過c,則選擇單位重量價值次高的物品並盡可能多地裝入揹包。依此策略一直地進行下去,直到揹包裝滿為止。

**實現:

float knapsack(float c,float w[maxnum], float v[maxnum],float

con[maxnum])

if (i

return

hascon;

}

演算法knapsack的主要計算時間在於將各種物品依其單位重量的價值從大到小排序。因此,演算法的計算時間上界為o(nlogn)。當然,為了證明演算法的正確性,還必須證明揹包問題具有貪心選擇性質。

對於0-1揹包問題,貪心選擇之所以不能得到最優解是因為在這種情況下,它無法保證最終能將揹包裝滿,部分閒置的揹包空間使每公斤揹包空間的價值降低了。事實上,在考慮0-1揹包問題時,應比較選擇該物品和不選擇該物品所導致的最終方案,然後再作出最好選擇。由此就匯出許多互相重疊的子問題。這正是該問題可用動態規劃演算法求解的另一重要特徵。

實際上也是如此,動態規劃演算法的確可以有效地解0-1揹包問題。

5.貪心演算法的適用範圍:

貪心演算法並不能總求得問題的整體最優解。但對於某些問題,卻總能求得整體最優解,這要看問題時什麼了。只要能滿足貪心演算法的兩個性質:貪心選擇性質和最優子結構性質,貪心演算法就可以出色地求出問題的整體最優解。即使某些問題,貪心演算法不能求得整體的最優解,貪心演算法也能求出大概的整體最優解。如果你的要求不是太高,貪心演算法是乙個很好的選擇。最優子結構性質是比較容易看出來的,但是貪心選擇性質就沒那麼容易了,這個時候需要證明。證明往往使用數學歸納法。

貪心演算法講解及例題

修改自 一 概念 貪心演算法是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的僅是在某種意義上的區域性最優解。貪心演算法沒有固定的演算法框架,演算法設計的關鍵是貪心策略的選擇。必須注意的是,貪心演算法不是對所有問題都能得到整體最優解,選擇的貪心策略必須...

經典貪心演算法 貪心演算法概述

貪心演算法具有最優子問題結構,它的特點是 短視 每次選擇對當前局面最有利的決策,來一步步獲得最優解。我個人認為,貪心不是乙個具體的方法,而是一類方法,貪心演算法的關鍵不在於想到,而在於正確性的證明。要證明乙個貪心演算法是正確的,需要證明我們可以把乙個最優解逐步轉化為我們用貪心演算法所得到的解,而解不...

演算法 貪心演算法

把乙個複雜問題分解為一系列較為簡單的區域性最優選擇,每乙個選擇都是對當前解的乙個擴充套件,知道獲得問題的完整解。在解決問題的策略上目光短淺,只根據當前已有的資訊做出選擇,而且一旦做出了選擇,不管將來有什麼結果這個選擇都不會改變。換言之,貪心法並不是從整體最優考慮,它所做出的選擇只是在某種意義上的區域...