雖然設計乙個好的求解演算法更像是一門藝術,而不像是技術,但仍然存在一些行之有效的能夠用於解決許多問題的演算法設計方法,你可以使用這些方法來設計演算法,並觀察這些演算法是如何工作的。一般情況下,為了獲得較好的效能,必須對演算法進行細緻的調整。但是在某些情況下,演算法經過調整之後效能仍無法達到要求,這時就必須尋求另外的方法來求解該問題。
本章首先引入最優化的概念,然後介紹一種直觀的問題求解方法:貪婪演算法。最後,應用該演算法給出貨箱裝船問題、揹包問題、拓撲排序問題、二分覆蓋問題、最短路徑問題、最小代價生成樹等問題的求解方案。
1.1 最優化問題
本章及後續章節中的許多例子都是最優化問題( optimization problem),每個最優化問題都包含一組限制條件( c o n s t r a i n t)和乙個優化函式( optimization function),符合限制條件的問題求解方案稱為可行解( feasible solution),使優化函式取得最佳值的可行解稱為最優解(optimal solution)。
例1-1 [ 渴嬰問題] 有乙個非常渴的、聰明的小嬰兒,她可能得到的東西包括一杯水、一桶牛奶、多罐不同種類的果汁、許多不同的裝在瓶子或罐子中的蘇打水,即嬰兒可得到n 種不同的飲料。根據以前關於這n 種飲料的不同體驗,此嬰兒知道這其中某些飲料更合自己的胃口,因此,嬰兒採取如下方法為每一種飲料賦予乙個滿意度值:飲用1盎司第i 種飲料,對它作出相對評價,將乙個數值si 作為滿意度賦予第i 種飲料。
通常,這個嬰兒都會盡量飲用具有最大滿意度值的飲料來最大限度地滿足她解渴的需要,但是不幸的是:具有最大滿意度值的飲料有時並沒有足夠的量來滿足此嬰兒解渴的需要。設ai是第i 種飲料的總量(以盎司為單位),而此嬰兒需要t 盎司的飲料來解渴,那麼,需要飲用n種不同的飲料各多少量才能滿足嬰兒解渴的需求呢?
設各種飲料的滿意度已知。令xi 為嬰兒將要飲用的第i 種飲料的量,則需要解決的問題是:
找到一組實數xi(1≤i≤n),使n ?i = 1si xi 最大,並滿足:n ?i=1xi =t 及0≤xi≤ai 。
需要指出的是:如果n ?i = 1ai < t,則不可能找到問題的求解方案,因為即使喝光所有的飲料也不能使嬰兒解渴。
對上述問題精確的數學描述明確地指出了程式必須完成的工作,根據這些數學公式,可以對輸入/ 輸出作如下形式的描述:
輸入:n,t,si ,ai(其中1≤i≤n,n 為整數,t、si 、ai 為正實數)。
輸出:實數xi(1≤i≤n),使n ?i= 1si xi 最大且n ?i=1xi =t(0≤xi≤ai)。如果n ?i = 1ai
在這個問題中,限制條件是n ?i= 1xi =t 且0≤xi≤ai,1≤i≤n。而優化函式是n ?i= 1si xi 。任何滿足限制條件的一組實數xi 都是可行解,而使n ?i= 1si xi 最大的可行解是最優解。
例1-2 [裝載問題] 有一艘大船準備用來裝載貨物。所有待裝貨物都裝在貨箱中且所有貨箱的大小都一樣,但貨箱的重量都各不相同。設第i 個貨箱的重量為wi(1≤i≤n),而貨船的最大載重量為c,我們的目的是在貨船上裝入最多的貨物。
這個問題可以作為最優化問題進行描述:設存在一組變數xi ,其可能取值為0或1。如xi 為0,則貨箱i 將不被裝上船;如xi 為1,則貨箱i 將被裝上船。我們的目的是找到一組xi ,使它滿足限制條件n ?i = 1wi xi ≤c 且x i ? , 1 ≤i≤n。相應的優化函式是n ?i= 1xi 。
滿足限制條件的每一組xi 都是乙個可行解,能使n ?i= 1xi 取得最大值的方案是最優解。
例1-3 [最小代價通訊網路] 城市及城市之間所有可能的通訊連線可被視作乙個無向圖,圖的每條邊都被賦予乙個權值,權值表示建成由這條邊所表示的通訊連線所要付出的代價。包含圖中所有頂點(城市)的連通子圖都是乙個可行解。設所有的權值都非負,則所有可能的可行解都可表示成無向圖的一組生成樹,而最優解是其中具有最小代價的生成樹。
在這個問題中,需要選擇乙個無向圖中的邊集合的子集,這個子集必須滿足如下限制條件:所有的邊構成乙個生成樹。而優化函式是子集中所有邊的權值之和。
Python之貪婪演算法
np完全問題 找不到快速演算法的問題。識別np完全問題,以免浪費時間去尋找解決它們的快速演算法 沒辦法判斷問題是不是np完全問題,但還是有一些蛛絲馬跡可循的。1 元素較少時演算法的執行速度非常快,但隨著元素數量的增加,速度會變得非常慢。2 涉及 所有組合 的問題通常是np完全問題。3 不能將問題分成...
演算法導論(六)之貪婪演算法
動態規劃是先分析子問題,再做選擇。而貪心演算法則是先做貪心選擇,做完選擇後,生成了子問題,然後再去求解子問題 活動集合s si為 開始時間 fi為 結束時間 s i為開始時間,f i 為結束時間 si 為開始 時間,f i 為結 束時間 i123 4567 891011 s is i si 130 ...
常見演算法思想之動態規劃 貪婪演算法
最近總是跟動態規劃打交道,索性就將其弄明白一點。所謂的動態規劃並不是一種具體的演算法,而是一種演算法的思想。思想總是抽象的,縹緲的。所以在學習動態規劃的時候會有一種很尷尬的情況,就是感覺這個東西很簡單,但是又不知道自己是不是真的學會了。簡單的來說,動態規劃就是將乙個大問題分解為子問題,然後根據子問題...