1. 程式人生 > >貪心演算法之活動選擇理解

貪心演算法之活動選擇理解

一.活動選擇事例

這裡寫圖片描述

二.例題分析

1、定義子問題
採用動態規劃的方法:
這裡寫圖片描述
2、尋找最優子結構:
假設已經找到問題Sij最大相容活動集Aij,如果Aij中包含Ak(屬於某一活動)。則可以將Sij分成兩個子問題Sik和Ak和Skj。此時Sik和Skj的最大相容活動集Aik和Akj一定被Aij使用。因為如果Aij沒有使用Aik和Akj的話,那麼它使用的就是Sik,Skj非最大相容子集。那麼就與我們假設的Aij為最大相容子集相悖。
3、重疊子:
與《動態規劃之矩陣鏈乘法理解》一樣,我們不知道k具體是多少,所以我們要對i~j遍歷賦值給k才能找出。而遍歷過程中要重複處理相同子問題。
4、自底向上方法:


如果使用動態規劃的方法的話,我們就需要從最小子問題逐漸增大來完成所有子問題的處理:
將從子問題個數為2開始,像先前劃分矩陣鏈一樣劃分,選擇出活動只有兩個時的最優A12,A23,A34~~,然後把活動分成3、4、5、6~~長度,逐漸增大子問題長度,求解最優解(在這過程中注意使用上先前已經求解的子問題)。
這裡寫圖片描述

三.動態規劃到貪心演算法的轉變

首先需要申明貪心演算法對大多數優化問題能夠產生最優解,但並不是對所有問題。

這裡寫圖片描述
證明2:如果將問題Sij(已按照結束時間從小到大排列)在am處劃分,將問題Sij劃分成Sim和Smj,由於Sim已經按照結束時間排序,那Sim為空集(裡面沒有活動),子問題Smj為唯一可能的非空子問題(Smj是Sij除掉一個最早結束時間活動的結果,其中包含活動數除Sij最大)。
證明1:假設Aij(最大相容子集)中包含了am,那麼顯然得證。如果Aij中沒有am呢?此時我們構建另一個子集A:它是包含(Aij)後減去(Aij中最早結束活動ae)+(am)。此時因為am比ae結束更早,而ae又是Aij中最早結束活動,那麼am就不會與Aij中活動產生衝突。那麼A包含的活動數並不少於Aij,那麼A就是問題Sij的另一個最大相容子集。且A中包含am。此時Aij和A都是最大相容子集。這裡也說明貪心演算法的最優解只是其中一個。
理解:


貪心演算法更像是不再迴圈k值,直接把問題Sij在最早結束活動那裡劃分成兩個子問題(其中一個子問題還為空),這樣我們就不需要考慮Sim(空集),只需考慮Smj,減少計算。而且這樣做我們就可以自頂向下考慮。從最大問題,逐漸縮小子問題。

四.程式碼

這裡寫圖片描述
圖解過程:
這裡寫圖片描述

看我畫的兩個紅色矩形。如果兩個方塊代表兩個活動。原題中按照演算法的話會選擇a1,但是如果不按照演算法來,先選擇第一紅色矩形,那麼選擇的第二個就是第二個紅色矩形,後面的選擇跟原題一樣。但是改變初始選擇後,算出來的最大相容子集明顯比原來大1。所以說貪心演算法得到的不一定是最優解。