算法图解第八章笔记与习题(贪婪算法)
算法圖解第八章筆記與習題(貪婪算法)
文章目錄
- 算法圖解第八章筆記與習題(貪婪算法)
- 8.1 貪婪算法
- 8.2 集合覆蓋問題
- 8.3 NP完全問題
- 8.3.1 旅行商問題:
- 8.3.2 如何識別NP完全問題
- 8.4 小結
- 練習
- 習題8.1:
- 習題8.2:
- 習題8.3-5題干:
- 習題8.3:
- 習題8.4:
- 習題8.5:
- 習題8.6:
- 習題8.7:
- 習題8.8:
算法圖解pdf百度云鏈接,提取碼:jttg
8.1 貪婪算法
貪婪算法:對于一個問題,根據問題要求的目標,每步都選擇局部最優解。在某些特定的情況下,貪婪算法能夠得到最優解,但通常只能能夠得到一個接近最優解的解。
舉例:從十個數中選擇五個使其和最大1,2,3,4,5,6,7,8,9,10。
根據問題要求的目標(和最大),每步都選擇局部最優解(從未被選擇的數中選擇最大的那個數)。對于這個簡單的情況來說,貪婪算法將得到最優解10+9+8+7+6=40。但對于更復雜的情況來說,通常會得到一個接近最優解的解。
8.2 集合覆蓋問題
假設現在有個廣播節目,要讓全美國50個州的聽眾都收聽得到,為此,需要決定在哪些廣播臺播出。在每個廣播臺播出都需要支付費用,因此必須在盡可能少的廣播臺播出。現有廣播臺名單如下:
每個廣播臺都覆蓋特定的區域,不同廣播臺的覆蓋區域可能重疊。
那么找出覆蓋全美50個州的最小廣播臺合集呢?下面是解決步驟:
這樣做固然能找到最優解,但其時間復雜度為O(2n)O(2^n)O(2n),其中n為廣播臺數量。在這種情況下,我們可以使用貪婪算法來解決這個問題。步驟如下:
這是一種近似算法(approximation algorithm)。在獲得精確解需要的時間太長時,可以考慮使用近似算法。判斷近似算法優劣的標準如下:
- 速度有多快;
- 得到的近似解與最優解的接近程度。
因此貪婪算法是一個不錯的選擇,它們不僅簡單,而且通常運行速度很快。在本例中,貪婪算法的運行時間為O(n2)O(n^2)O(n2),其中n為廣播臺數量。
代碼如下:
# 創建一個列表,其中包含要覆蓋的州 states_needed = set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"]) # 傳入一個數組,被轉換為集合stations = {} stations["kone"] = set(["id", "nv", "ut"]) stations["ktwo"] = set(["wa", "id", "mt"]) stations["kthree"] = set(["or", "nv", "ca"]) stations["kfour"] = set(["nv", "ut"]) stations["kfive"] = set(["ca", "az"])final_stations = set() # 使用一個集合來存儲最終選擇的廣播臺while states_needed:best_station = None # 將覆蓋了最多的未覆蓋州的廣播臺存儲進去states_covered = set() # 一個集合,包含該廣播臺覆蓋的所有未覆蓋的州for station, states in stations.items(): # 循環迭代每個廣播臺并確定它是否是最佳的廣播臺covered = states_needed & states # 計算交集if len(covered) > len(states_covered): # 檢查該廣播臺的州是否比best_station多best_station = station # 如果多,就將best_station設置為當前廣播臺states_covered = coveredstates_needed -= states_covered # 更新states_neededfinal_stations.add(best_station) # 在for循環結束后將best_station添加到最終的廣播臺列表中print(final_stations) # 打印final_stations set(['ktwo', 'kthree', 'kone', 'kfive']) #(算法也可以用未被覆蓋的州來做比較,未被覆蓋的州越少,則該廣播臺是局部更優的廣播臺。)上述代碼中,set()是一種集合,類似于列表,但相同的元素在其中出現一次,也沒有索引供查找。
另外,還涉及到了數學中交集的計算&,以及集合間相見-=。具體不做詳細介紹。
使用上述貪婪算法的運行時間僅為O(n2)O(n^2)O(n2),比起遍歷所有子集來獲得精確解的精確算法O(2n)O(2^n)O(2n)來說非???。
8.3 NP完全問題
8.3.1 旅行商問題:
旅行商問題是指,旅行商需要在一次旅行中途徑多個不同的城市,如何求解其最短路徑。
對于 1 個城市而言,僅有 1 條可能的路徑。
對于 2 個城市而言,有 2 個可能的起點X每個出發的城市1條可能的路徑 = 2條可能的路徑。
對于 3 個城市而言,有 3 個可能的起點X每個出發的城市2條可能的路徑 = 6條可能的路徑。
對于 4 個城市而言,有 4 個可能的起點X每個出發的城市6條可能的路徑 = 24條可能的路徑。
對于 5 個城市而言,有 5 個可能的起點X每個出發的城市24條可能的路徑 = 120條可能的路徑。
……
這是一個階乘函數(factorical function),當涉及的城市越多時,可能的路徑條數增加的非??臁R虼水斏婕暗某鞘凶銐蚨鄷r,根本就難以計算出旅行商問題的正確解。
NP完全問題的簡單定義是,以難著稱的問題,如旅行商問題和集合覆蓋問題。(?)
8.3.2 如何識別NP完全問題
NP完全問題無處不在!如果能夠判斷出要解決的問題屬于NP完全問題就好了,這樣就不用去尋找完美的解決方案,而是使用近似算法即可。但要判斷問題是不是NP完全問題很難,易于解決的問題和NP完全問題的差別通常很小。
但事實是沒辦法判斷問題是不是NP完全問題,但還是有跡可循的:
- 元素較少時算法的運行速度非常快,但隨著元素數量的增加,速度會變得非常慢。
- 涉及“所有組合”的問題通常是NP完全問題。
- 不能將問題分成小問題,必須考慮各種可能的情況。這可能是NP完全問題。
- 如果問題涉及序列(如旅行商問題中的城市序列)且難以解決,它可能就是NP完全問題。
- 如果問題涉及集合(如廣播臺集合)且難以解決,它可能就是NP完全問題。
- 如果問題可轉換為集合覆蓋問題或旅行商問題,那它肯定是NP完全問題。
8.4 小結
- 貪婪算法尋找局部最優解,企圖以這種方式獲得全局最優解。
- 對于NP完全問題,還沒有找到快速解決方案。
- 面臨NP完全問題時,最佳的做法是使用近似算法。
- 貪婪算法易于實現、運行速度快,是不錯的近似算法。
練習
習題8.1:
- 你在一家家具公司工作,需要將家具發往全國各地,為此你需要將箱子裝上卡車。每個箱子的尺寸各不相同,你需要盡可能利用每輛卡車的空間,為此你將如何選擇要裝上卡車的箱子呢?請設計一種貪婪算法。使用這種算法能得到最優解嗎?
將剩余箱子中最大的一個裝入箱子,直到將所有的箱子裝入卡車為止。使用這種算法不能找到最優解。
習題8.2:
- 你要去歐洲旅行,總行程為7天。對于每個旅游勝地,你都給它分配一個價值——表示你有多想去那里看看,并估算出需要多長時間。你如何將這次旅行的價值最大化?請設計一種貪婪算法。使用這種算法能得到最優解嗎?
從剩余未去過的旅游勝地中選擇價值最高的,直至時間用完為止。使用這種算法不能找到最優解。
習題8.3-5題干:
- 下面各種算法是否是貪婪算法。
習題8.3:
- 快速排序。
不是。
習題8.4:
- 廣度優先搜索。
是。
習題8.5:
- 狄克斯特拉算法。
是。
習題8.6:
- 有個郵遞員負責給20個家庭送信,需要找出經過這20個家庭的最短路徑。請問這是一 個NP完全問題嗎?
是??赊D化為旅行商問題。
習題8.7:
- 在一堆人中找出最大的朋友圈(即其中任何兩個人都相識)是NP完全問題嗎?
是。可轉化為集合覆蓋問題。
習題8.8:
- 你要制作美國地圖,需要用不同的顏色標出相鄰的州。為此,你需要確定最少需要使用多少種顏色,才能確保任何兩個相鄰州的顏色都不同。請問這是NP完全問題嗎?
不是。(圖著色問題,是NP完全問題。)
總結
以上是生活随笔為你收集整理的算法图解第八章笔记与习题(贪婪算法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解STM32内存管理
- 下一篇: 宽容与忍耐 忍乃济——这是《尚书》这部中