演算法考試複習之胡思亂記 貪心法

2021-04-01 02:45:51 字數 2702 閱讀 6059

貪心法

貪心法顧名思義就是說要貪,要一點一點的貪,歇斯底里地貪,嚼字一點的講,就是說求乙個問題的最優解時,將這個問題肢解為一系列的區域性性的問題,然後通過在每個區域性得到最優以使得在全域性得到最優.其實這點挺有意思的,整個計算機界每天都在叫著虛擬實境,為此做了很多的演算法,大部分演算法都比較貪,結果現實給我們虛擬出來了.當然,即使在現實世界裡面貪也就不見得全是壞事,所以這麼想來也只能說是現實世界是比較殘酷的吧.可以想象,差不多所有寫程式不貪的程式設計師都下崗或面臨下崗了吧.

當然對於區域性最優到全域性最優這個過程是不是可行的,不同的解決方法自然有不一樣的答案了,如果你的方法是對的,歸納法會告訴你的,如果你的方法是錯的,歸納法也會告訴你的.

經典問題之一是圖的最小生成樹的演算法.生成樹的意思就是說包含圖中所有頂點的連通無環的子圖,而最小生成樹是指在生成樹裡面樹的權重最小的那乙個棵。主要的方法有prim演算法和kruskal演算法.

1. prim演算法

它是bell的r. c. prim在57年提出的演算法,不過他也並不全是這個演算法最最祖先的人,最早的應該是捷克人v. jarník在2023年提出的演算法,不過他的文章是用捷克語寫的,光看標題就看不明白了。有人也把這個演算法就叫做prim-jarnik演算法。prim演算法簡單有效,他從圖的乙個指定的頂點出發,用v表示樹頂點集,初始只有那個指定的頂點;e表示最終最小生成樹中有的邊的集合,初始是空集。從v中的頂點出發,找到從這個頂點出發的權值最小的邊,如果這條邊不構成回邊,那麼選入最小生成樹,並將這條邊加到e集合中,邊的另一端結點加入到v集合中。這樣一直迴圈到v中的頂點為圖的所有頂點為止,最小生成樹就存在e集合裡面了。

證明這個演算法是否正確還是利用歸納法,在從t(i-1)是最小生成樹到t(i)是最小生成樹的判定過程中使用反證法,就可以證明這樣選出來的樹一定是最小生成樹。

顯然這個演算法還有它的提公升空間,但是不管怎麼提公升,基礎性的想法不會有什麼變化,所以不會有什麼質的差別,不值得再提了。這就是基礎科學的魅力,它是57年的演算法,人們到今天還會津津樂道。

2. kruskal演算法

這個演算法是kruskal j.b在2023年的**裡面提出來的,又是乙個爺爺級的演算法。它從邊的角度出發,每一次將圖中的權值最小的邊取出來,在不是回邊,也就是說不構成環的情況下,將邊加入最小生成樹中,重複這個過程,直到所有的圖中所有的點都加入到最小生成樹中結束。

3. 兩種演算法的比較

從空間上講,顯然在prim演算法中,我們只需要很小的空間就可以完成演算法,因為每一次我們都是從個別點開始出發進行掃瞄的,而且每一次掃瞄也只掃瞄與當前頂點集對應的邊,但在kruskal演算法中,因為我們每時每刻都得知道當前的樹裡面權值最小的邊在**,這樣我們需要對所有的邊進行排序。對於很大的圖來講,這個需要占用比prim演算法大的多的空間。從時間上講,prim演算法如是果用linked list表示圖,用最小堆實現優先順序對列的話,演算法的複雜度為o(|e|log|v|),而在kruskal演算法中,如果排序演算法很高效的話,kruskal演算法的時間複雜度為o(|e|log|e|),這樣比起來,好像prim演算法的確比kruskal演算法更好一些。

第二個經典的問題也是跟圖有關,dijkstra演算法

大家都了解dijkstra是acm圖靈獎的獲得者,荷蘭人。他在演算法,作業系統,分布式處理等許多方法都有極高深的造詣,他於2023年從大學中正式退休,在2023年8月去世。他的一生絕對可以算得上是那種直接叫amazing life的那種的了,是乙個計算機科學家可以達到的頂點位置。這個演算法是在59年發表的,當時的dijkstra29歲,從阿姆斯特丹大學博士畢業,當了程式設計師6年程式設計師之後,天才加經驗了,完全的無敵模式。這個演算法發表3年之後,在2023年他就回到大學開始當教授,並開始一次次創造奇蹟,創造歷史。

dijkstra演算法研究的問題是單起點最短路徑的問題。它的輸入就是乙個連通圖,再加上乙個頂點s。輸出對於圖中所有頂點來說從起始頂點s到它們的最短路徑長度和路徑上的倒數第二個頂點。

在用鄰接鍊錶表示圖,最小堆表示優先佇列的情況下,dijkstra演算法的複雜度為o(|e|log|v|)。

第三個經典問題是揹包問題。就是n件物品乙個可以容納重m的物品的包,每件物品的重量不一樣,且他們的價值也都不一樣,用怎麼樣的方式來把物品放在包裡面,以使包中的物品的價值最大。如果每件物品可以分成幾份的話,就是廣義的揹包問題,如果一件物品要麼拿要不就不拿,這個問題歸為0/1揹包問題。

這個問題其實最好地展示了貪心這個概念,涉及到價值了,而且有一種想搶又怕手短的急迫感。解決方法當然其實相當簡單的,要不你用物品的價值排序,用價值當標準來選,直到選到不能再裝為止。要麼用價值除去重量排序,按這個排序的結果順序能裝多少裝多少,就是乙個價重比高者優先的想法。也就是說在貪心的世界裡面,走出的每一步都像是老媽在買菜一樣,穩,準,狠,不到萬不得已,決不放手。不過可以證明的是,當用價重比進行排序裝包的時候,得到的結果是最優的。證法當然還是歸納法。

更有趣的是,如果要裝的物品是人的話,我又是物品中的乙個,不管用哪種排序,我都不會被選中而放到包裡,這再一次證明世界是殘酷的,尤其對於體重超過一定數量的人來說。。。。。。

第四個問題為處理器排程問題,假定有n個處理機,m個任務,每個作業占用處理機的時間一定,如何將作用分配給各個處理機。第一種方法就是按作業進行操作的順序直接分,當前最閒的處理機執行下乙個任務。直到分完所有的任務。這個方法當然不是最優的,像是早期紙帶機的那種順序操作的感覺。第二種方法就是將作業要用的時間排序,然後將作業分給當前最空閒的處理機。這種方法聽起來有點像多程序排程的方法。事實上這兩種方法都不是最優的,在動態規劃和分支限界法裡面有更優的方法可用.

貪心法大概就這麼多了,當然涉及到演算法細節和實現的時候會遇到更多的問題,不再繼續下去了,必竟是個考試,抓面不抓點的做法是比較「貪心」的選擇,收穫會大一點,回頭有時間好好往細搞。

基礎演算法之貪心法1

1.2貪心法 1 在某些情況下區域性最優選擇能得出全域性最優解。如下。例1.刪數問題 int main if max 0 weight 0 不使用 價值分別為value 6 value 0 不使用 要求總重量不超過12。我們先建立乙個陣列,array 6 12 array m n 表示標號為m及標號...

演算法學習之貪心法

貪心法是在對問題進行求解時,只做出在當前情況下最好的解,即區域性最優解 而動態規劃是整體最優解 建立數學模型,來描述問題 把問題分解成若干個子問題 對每一子問題求解,得到子問題區域性最優解 把每乙個子問題的區域性最優解合併成乙個解 有n個需要在同一天使用同乙個教室的活動a1,a2,an,教室同一時刻...

演算法 五大演算法之貪心法

貪心法 greedy algorithm 又稱貪心演算法,是一種在每一步選擇中都採取在當前狀態下最好或最優 即最有利 的選擇,從而希望導致結果是最好或最優的演算法。1.基本概念 貪心演算法與動態規劃的不同在於它每對每個子問題的解決方案都做出選擇,不能回退。動態規劃則會儲存以前的運算結果,並根據以前的...