關於貪心算法的經典問題(算法效率 or 動態規划)


如題,貪心算法隸屬於提高算法效率的方法,也常與動態規划的思路相掛鈎或一同出現。下面介紹幾個經典貪心問題。(參考自劉汝佳著《算法競賽入門經典》)。
P.S.下文皆是我一個字一個字敲出來的,絕對“童叟無欺”,哈哈。(。⌒∇⌒) 耗費了我的很多時間,所以——希望對大家有幫助啊~ (=^‸^=)

一、背包相關問題

1.最優裝載問題:給出N個物體,有一定重量。請選擇盡量多的物體,使總重量不超過C。
解法:只關心數量多,便把重量從小到大排序,依次選,直到裝不下。

2.部分背包問題:給出N個物體,有一定重量和價值。請選擇一些物體的一部分使在總重量不超過C的條件下總價值最大。
解法:關心總價值大,物體可取部分,便優先取單位重量價值較大的物體。

3.乘船問題:有N個人,有一定重量。每艘船的最大載重量均為C,且最多載2人。請用最少的船裝載所有人。
解法:關心數量少,要盡量使每艘船的實際載重量盡量接近於最大載重量。便把重量從小到大排序,每艘船依次先載一個人,再載重量最接近船的剩余可載重量的人。這樣可以使眼前的消費(剩余載重量)最少。
實現:用2個變量 l , r 分別從兩頭往中間移動,l 和 r 可共乘一艘船,或 r 自己乘一艘船。

 

二、區間相關問題

1.選擇不相交區間:數軸上有N個開區間(Li,Ri),請選擇盡量多個區間,並保證這些區間兩兩沒有公共點。
解法:先把這些區間按找 Ri 從小到大的順序排序,再對按序排列的每2個區間A,B分情況討論:(1)A被B包含,選A最優;(2)A右邊的一部分與B左邊的一部分相交,選A最優,因為選A比B減少了與后面區間相交的可能性;(3)A、B不相交,便2個都選。總的來說就是排序后,從左到右選第一個沒有與前面已選的區間相交的區間。O(n)。
拓展:那么如果可以一共覆蓋兩次,那該怎么選?         ——也就是【bzoj3433】{Usaco2014 Jan}Recording the Moolympics(算法效率--貪心)

2.區間選點問題:數軸上有N個閉區間[Li,Ri],請選擇盡量少的點,使得每個區間內都至少有一個點。
解法:同樣地先把這些區間按找 Ri 從小到大的順序排序,再分類討論:(1)A被B包含,不需理會B; P.S.沒有明顯的思路就暫時不推到具體選哪一個點 (≡・ x ・≡) (2)A右邊的一部分與B左邊的一部分相交,當拓展到3個或以上都有一部分重疊時,肯定選第一個區間的右端點,以使這個點處於更多的區間內;(3)A、B不相交,便各自隨意填一個點。總的來說就是排序后,從左到右選第一個沒有與前面已選的區間相交的區間的右端點。O(n)。

3.區間覆蓋問題問題:數軸上有N個閉區間[Li,Ri],選擇盡量少的區間覆蓋一條指定線段[s,t]。
實現:先預處理一遍把線段外的區間的所有部分去掉,然后按 Li 從小到大的順序排序,選當前 Ri 最大的。再選剩下的起點在剛選完的區間的右端點之前的右端點最右的區間。O(n)。

 

三、Huffman編碼

最優編碼問題:給出N個字符的頻率 ci ,給每個字符賦予一個01編碼串,使得任意一個字符的編碼不是另一個字符編碼的前綴,而且編碼后總長度(每個字符的頻率與編碼長度乘積的總和)盡量小。

解法:
   Step 1.從01串,轉換為構造一棵最優的編碼樹,左孩子是0,右孩子是1。而由於是編碼,不能其中一個是另一個的前綴,便所有的字符都是葉子結點,不存在任一個是另一個的祖先,且要最優便不會葉子結點不是一個編碼。。。
   Step 2.轉換問題之后便用Huffman算法就可以了。∠※  把每個字符看作一個單結點子樹放在一個樹集合中,每棵子樹的權值等於相應字符的頻率。每次取權值最小的兩棵子樹合並成一棵新樹,並重新放到集合中。新樹的權值等於兩棵子樹權值之和。可以通過2個結論證明其正確性:1.貪心選擇性質,使得第一步貪心法選擇保留最優解。設x和y是頻率最小的兩個字符,則存在前綴碼使得x和y具有相同碼長,且僅有最后一位編碼不同;2.最優子結構性質,使得原問題的最優解包含子問題的最優解。設 x 和 y 是有相同父親結點 z 的兩個葉子結點,那么把它們兩個去掉,而留下 z 的最優編碼樹不會變。即——通過確定“”就知道這個算法是正確的啦。

實現:先按照頻率把所有字符排序為一個隊列P,再建一個隊列Q存新的結點。先合並P最前面的2個結點后把新結點放在另一個隊列Q,刪除這2個結點。由於兩個隊列都是有序的,就可以接着從P最前面的2個結點后Q的前2個結點中選出2個頻率最小的結點合並,新結點同樣放在另一個隊列,知道隊列P為空。所以總時間復雜度是O(n log n+n)≈O(n log n)。我之前打過一道運用了這個知識點的題——【uva 10954】Add All(算法效率--Huffman編碼+優先隊列)


免責聲明!

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



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