優化問題的算法通常會通過一系列的步驟,在每一個步驟通過一系列的選擇。一個貪婪算法總是目前看起來最好的選擇。也就是說,它做出局部最優選擇,希望選擇將導致全局最優的解決方案。貪心算法並不總是能得到最優解,但對於許多問題它們都能得到最優解。
活動選擇問題
幾個相互競爭的活動需要共同的資源,目標是在活動不發生衝突的前提下,選出最多可舉辦的活動數。假設我們有一個集合提議希望使用資源的活動,例如一次只能由一個活動使用的演講廳。每個活動ai都有一個開始時間si和一個結束時間fi, 。如果選擇,活動ai發生在半開時間間隔[si,fi)的情況下,活動ai和aj是兼容的,間隔[si,fi)和[sj.fj]不重疊的。活動選擇問題是選擇相互兼容的活動的最大子集。
按開始時間最早的排序;X
按時間間隔最短的排序;X
按結束時間最早的排序;√
最小生成樹問題(Minimum spanning trees,MST)
在電子電路的設計中,把幾個零件的引腳連接在一起就通電了。互連一組n個引腳,我們可以使用一個n-1線的排列,每根連接2個引腳。在所有這些安排中,使用的那個最少的電線通常是最多的引腳。我們可以用一個連通的無向圖G=(V,E)來建模這個佈線問題,其中V是引腳的集合,E是引腳對之間可能的相互連接的集合,對於E中的每條邊(u,v),我們都有一個權值w(u,v)來指定連接u和v的代價(所需的導線數量),需要找到無圈的子集把所有的引腳連接起來,並使得權值最小。因爲T是非圈的,並且連接所有的頂點,所以它必須形成一棵樹,我們稱之爲G的生成樹,T就是最小生成樹。
假設有一個連通的無向的圖G=(V,E),及權值函數。我們希望找到G的最小生成樹。我們在這裏考慮的兩個算法使用貪婪的方法解決問題。
這個貪心策略由下面的“一般型”算法延伸,該算法每次只增長最小生成樹的一條邊。該算法管理邊集A,A不斷加1條邊,需要做n-1次循環。在每次迭代之前,A是最小生成樹的子集。在每一步,我們確定可以添加到A的邊{u,v},在不違背這個不變式的情況下,還是最小生成樹的一個子集。我們稱這樣的邊爲A的安全邊,因爲它可以在保持不變的情況下添加到A。
GENERIC-MST(G,w) A ← Ø while A does not form a spanning tree do find an edge e that is safe for A A ← A ∪ e return A
如何找到安全的邊?
我們首先需要一些定義。無向圖G=(V,E)的一個cut(S,V-S)是V的一個分劃。如果它的一個端點在S中,另一個端點在V-S中,我們說一條在E中的邊(u, v)穿過這個cut(S,V-S)。如果A中的邊沒有與該cut相交,則該cut respects A組邊。如果邊的權值是任何邊穿過cut的最小值,則邊就是穿過cut的輕邊。注意,還可以有更多輕邊,那麼選擇其中一條即可。簡單來說,就是A+安全邊就是最小生成樹的子集,A中的點沒有穿過cut,再在cut中找到輕邊作爲安全邊,得到新的A,然後再找到新的cut,滿足A沒有穿過cut,循環此過程,直至找到n-1條邊。
定理:設G=(V,E)是連通的具有權重w的無向圖,令A是E的子集,包含在G的最小生成樹中。設(S, V-S)爲任意cut(respect A),設(u,v)爲穿過(S, V-S)的輕邊。那麼(u,v)是A的安全邊。
證明:設T是一個最小生成樹,包含A,並假設T不包含輕邊(u,v)。如果是這樣,我們就完成了。我們將構造另一棵最小生成樹T',通過使用cut-and包括U {U,v}粘貼技術,從而顯示(u,v)是aA的安全邊。
邊(u,v)與在T中路徑p從u到v的邊形成一個循環,因爲u和v是cut(S, v -S)的相對邊,所以在路徑p中至少有一條邊也穿過cut。設(x,y)是任意一條這樣的邊。這條邊(x,y)不在A中,因爲cut respect A。因爲(x,y)在T中從u到v的唯一路徑上,所以刪除(x,y)把T分成兩個部分。添加(u, v),從新的生成樹重新連接它們接下來證明T'是最小生成樹。因爲(u,v)是一個輕的邊緣交叉(S, v -S)和(x,y)也穿過這條線,w(u,v)<=w(x,y)因此,w (T ') = w (T) - w (x, y) + w (u, v) < = w (T)。但是T是最小生成樹,所以T'也必須是最小生成樹。
對於當前生成樹T,u,v之間沒有直接的邊相連,但可以通過路徑p連通,按圖中將G分割爲cut兩部分,使得u, v在cut不同的點集,那麼必然存在這樣 的x,y也被劃分在cut兩部分,邊(u,v)(x,y)都穿過該cut,(u,v)是輕邊,連接(u,v),斷開(x,y),得到新的生成樹T‘,而且(u,v)是輕邊,那麼T(w)≥T'(w)。
Kruskal , Prim它們使用特定的規則來確定安全邊界。
克魯斯卡爾算法(Kruskal)和Prim算法
集合A是一個森林。添加到A的安全邊總是圖中連接兩個不同組件的最小權重邊(即選擇圖G中未連接的權值最小的邊)。在Prim的算法中,集合A形成一個單一的樹。添加到A的安全邊總是最小權值將樹連接到不在樹中的頂點的邊(從當前解的生成樹往外連接權值最小的邊)。
Prim算法: 假設從a出發,先走ab,bc和ah的權值一樣,任選一條,這裏走bc,w(ci)<w(ah),那麼走ci,w(cf)<w(cd)=w(ih)<w(ah),那麼走cf,按照這種思路,走fg,gh,cd,de。
爲了驗證正確性,可以從任意點出發,再次選擇一遍,結果是一樣的,假設從d出發,下圖是按d出發的cut選擇。
Kruskal算法:按照權值從小到大連接,最小的是w(hg)=1,那麼選擇過程:hg,gf,ci,cf,ab,cd,cb,de。下圖顯示前五步選擇。
最大獨立集(Maximum independent set)
我們要找到最大的獨立集合。如果我們用貪心算法解決問題,假設頂點的度越小越好。事實上,每當我們加上一個點到目前的解,我們也要把它的所有鄰居都清除掉。因此,首先選擇度較小的頂點可能會使我們獲得一個最大的獨立集。
Greedy independent set
input Graph G=(V,E);
output independent set V' in G;
begin
V':=ф
U:=V
while U is not empty do
begin
x: vertex of minimum degree in graph induced by U
V':=V'U(x);
eliminate x and all its neighbors from U
end
return V'
end
貪心算法找不到最大獨立集的例子:
a是最小度的點,a放入解集,刪除鄰居b,c,d,剩下e,f,g任選一個點,那麼最大獨立集爲兩個點。但最大獨立集是三個點{b,c,d}。
可以看出,存在一個頂點數不斷增加的圖序列,對於這個圖序列,該算法所得到的解的度量值與最優值相差甚遠。
可以使用圖的密度函數判斷貪心算法的表現。
定理:假設圖G有n個點和m條邊,記爲圖G的密度。貪心算法求得的解
證明:
證明:設xi爲程序while循環第i次迭代時選定的頂點,di(刪除鄰居後子圖的度)爲xi的度。然後,該算法將xi及其所有di鄰居從G中刪除。第i步刪除di+1個點,得到第一個式子,又因爲刪除點的同時會刪除邊,那麼與xi相連的di個點至少度是di,那麼刪除的邊有(di+1)di,di個點之間可能存在互相連接的情況,那麼刪除的邊至少有(di+1)di/2,刪除的邊數一定小於總邊數,得到第二個式子,(2)*2+(1)得到。利用柯西斯瓦格不等式,對於所有的i,當時,不等式的左邊取得極小值。,定理得證。
下面的定理提供了最優解與貪婪算法求得的解之間的關係。
定理:有n個頂點和m的圖G,設。程序找到一個獨立的集合,令最優解。
證明:本證明與前一證明相似。在本例中,我們在在(2)中另外計算與某個最優解的頂點相關聯的邊的數目。即,確定一個最大的獨立集合V*,令ki爲在第i次循環中所刪除di+1個頂點並在V*中的頂點數。明顯地,,由於貪心算法選擇的頂點最小度,刪除的頂點的度的和至少是di(di+1)。因爲一條邊的兩個端點不可能都在V*中,它這樣刪除邊的數目至少爲(di(di+1)+ki(ki-1))/2,這裏可以提高(2),得到,(2)+(3)+2*(4)得到。應用CS不等式,當,上述不等式左邊最小,因此,,即,當m*(G)=n時,不等式最小。通過把這一項代入,定理就成立了。
揹包問題(Greedy knapsack)
輸入:集合X的n個元素,對於X中的每個xi,價值pi,重量wi,正整數b;
輸出:子集使得
按pi/wi的規則進行貪心選擇。
begin
sort X in non-increasing order with respect to the ratio pi/wi;
Y:=empty set;
for i=1 to n do
if b>=wi then
begin
Y=YU{xi}
b=b-wi
end
return Y
end
反例:
例:令pi=wi=1,i=1,2,..,n-1, pn=b-1, wn=b=kn,其中k是一個任意大的數。在這種情況下,最優解m*(x)=b-1;而貪心算法找到的解的值爲n-1。因此m * (x) /mGr(x) > k。
發現貪心算法的劣勢是由於算法沒有將價值最高的元素包含在解中,而最優的元素正是價值最高的。這表明一個簡單的修改貪心的程序有更好的性能。
定理:給定一個揹包的實例x,令mH(x)=max(Pmax,mGr(x)),其中Pmax是x中一個項目的最大價值,mH(x)滿足以下不等式:。
證明:設j爲根據貪心選擇第一個裝不進揹包物品的下標,此時揹包轉裝入的物品價值爲,重量爲。我們首先證明任何最優解必須滿足以下條件不等式:,(因爲裝入前j-1個物品後,容量還剩餘,貪心選擇在裝入j-1個物品後,無法裝入j,其密度爲pj/wj,那麼如果剩餘容量按最優的去放,)。如果,那麼;如果,那麼,有
The Stein-lovasz Theorem(ST)
定理:設A是一個N行M列(0,1)矩陣。假設每一行至少包含v個1,每一列至多包含a個1。然後存在一個NXK子矩陣C(沒有全0行,每一行至少有一個1的矩陣)滿足:。可以想象爲關聯矩陣,每一列用超邊連接,如何用最少的超邊把所有的行覆蓋掉,每條超邊覆蓋的點滿足,利用貪心策略,每一步的超邊儘可能選最多的行。
舉例:
點集X={1,2,3,4,5,6},超邊集合={{1,3,4},{2,4,5},{1,5},{3,5},{5,6},{4},{6}},從超邊集合選擇最少的子集合,覆蓋所有的行,那麼選擇{1,3,4},{2,4,5},{6}最少的超邊子集合。
證明:
假設,表示由a個1且每列的1互不重合的列組成的矩陣,,那麼刪除覆蓋的行得到新的矩陣,那麼每一列至多有a-1個1,表示由a-1個1且每列的1互不重合的列組成的矩陣,,那麼刪除覆蓋的行得到新的矩陣,以此類推。,每行至少v個1,每列至多i-1個1,那麼有行,令其記爲,有列。,即,令,則,以此類推得到,。使用雙計數,分別對行和列進行計數,對於,每一行至少v個1,而每列至多i-1個1,可得對1進行行計數不會超過進行列計數,即,,那麼。
應用:
1. 完美哈希族
(n,m,w)-完美哈希族是一個函數F集合,使得|Y|=n, |X|=m, 對於F中的每一個f,對於任何使得,C是Y的w元子集合,並且至少存在一個F中的f使得f|C是一一對應的。如果|F|=N那麼完美哈希族可以記作PHF(N;n,m,w)。
|F|=N,如上圖,假設w=3,那麼任選Y中的三列,有種選擇,要求其中存在一行使得三個函數值各不同,例如取1,2,3列,f11,f12,f13互不相同就滿足要求一一映射。
,n個Y對應到m個X,每一個Y有m種選擇,那麼有個函數。從中挑出最少的函數(即上圖的N越小越好)使得對於任何的C可以滿足一一對應要求。
套用ST定理,找到對應的N,M,v,a,套用公式,就可以得到函數數目的一個上界。
需要完成的事情,從個函數中挑選出最少的函數滿足要求,那麼得到的矩陣就是NxM的(0,1)矩陣A,Aij=1的含義就是當|w|=i,fj是可以滿足一一映射要求的。,表示從m個值中選取w的值排列放入選擇的w個,剩餘未賦值的n-w個,就任意賦值。,每一個函數至多覆蓋a個。套用ST定理得。
使用概率方法,從個函數中隨機選擇N個函數出來,構造一張隨機的函數表,考慮壞概率,在函數表中沒有一個函數可以使w存在一一映射關係,對於一個函數壞概率爲存在一一對應關係的對立事件,取出N個函數,得,使其小於1,那麼一定存在完美哈希族。(兩邊取對數求解)
2.分割系統(Splitting Systems)
在某個域中,,已知且爲離散的,那麼如何求解n?分割系統的提出就是爲了解決離散對數問題。
假設n,t爲偶數,0<t<n,(n,t)分割系統是滿足下列要求的集合(X,)(X是點集合,是超邊集合):
a) |X|=n, 是X的n/2子集的集合,稱爲區組
b)對於每一個使得IY|=t,在中存在區組B,使得。
最少N的B使得上面的條件滿足。
使用ST定理,,對所有的t元子集合進行分割,,完成的方法總數,接下來確定v,那麼對於某一行有多少n/2元子集合可以分割ti,t個位置中一半放1,剩餘一半放0,問題是一個n元集合,此時還剩n-t個位置沒有放數,且還缺少(n-t)/2個1,那麼得到子集合個數;確定a,對於固定的n/2元子集合可以分割多少t,,套用ST定理,
使用概率方法:
定義Ai,第i個t元子集合未被分割。對於一個t元集合沒有分割的概率是分割時間的對立事件,爲,共有N個n/2元子集合未被分割,爲,那麼至少有一個t元集合未被分割的概率爲,令其小於1,那麼沒有未被分割的情況概率大於0。