1. 程式人生 > >利用python詳講貪婪演算法

利用python詳講貪婪演算法

貪婪演算法(又稱貪心演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的是在某種意義上的區域性最優解

貪婪演算法不是對所有問題都能得到整體最優解,關鍵是貪婪策略的選擇,選擇的貪婪策略必須具備無後效性,即某個狀態以前的過程不會影響以後的狀態,只與當前狀態有關。

下面我將用python結合問題例項來詳細講述此演算法

問題描述:

如下圖所示,有5個廣播臺,以及8個州,每個廣播臺的覆蓋範圍只有幾個州,現需要求得:最少需要那幾個廣播臺能實現州的全覆蓋

現在先建立模型

每個廣播站的模型如下

stations = {}
stations["kone"] = set(["id","nv","ut"])#廣播一
stations["ktwo"] = set(["wa","mt","id"])#廣播二
stations["kthree"] = set(["or","ca","nv"])#廣播三
stations["kfour"] = set(["nv","ut"])#廣播四
stations["kfive"] = set(["ca","az"])#廣播五

用一個集合states_needed 儲存所有的州

states_needed = set(["mt","wa","or","id","nv","ut","ca","az"])#所有需要覆蓋的州

思想如下:

每次找出當前能覆蓋州數最多的廣播臺(只注重當前最佳方案,是貪婪演算法的核心)

那麼本題的核心是:遍歷當前模型,先找出一個當前能覆蓋的州數最多的廣播臺

毫無疑問第一個被找出的廣播臺是kone,它覆蓋了三個當前未被覆蓋的州,分別是ID,NV,UT,於是kone被選中。

剩下的未被覆蓋的州是:WA,MT,OR,CA,AZ

接著遍歷,到了ktwo,它覆蓋了兩個當前未被覆蓋的州,分別是WA,MT

,在當前剩餘的廣播臺中沒有廣播臺比其覆蓋當前未被覆蓋的州數多了,那麼接下來被選中的是ktwo

剩下的未被覆蓋的州是:OR,CA,AZ

同理,接下來第三次迴圈,被選中的是kthree,它覆蓋了兩個當前未被覆蓋的州,分別是OR,CA

剩下的未被覆蓋的州是:AZ

然後,關鍵第四次迴圈了,按流程,下一次到kfour了,但是,其覆蓋當前未被覆蓋的州數為0,kfive覆蓋當前未被覆蓋的州數為1,此時kfive覆蓋當前未被覆蓋的州數目最多,於是剩下的被選中的廣播臺是kfive

演算法描述完畢

程式碼實現:

用另一個集合final_stations儲存每次被選中的廣播臺

final_stations = set()#最終選擇的廣播臺集合

完整實現程式碼(演算法部分):

#貪婪演算法
while states_needed:#當所有的州都被覆蓋後終止迴圈
    best_station = None#記錄當前覆蓋未被覆蓋的州數目最多的廣播臺
    states_covered = set()#記錄某廣播臺覆蓋(覆蓋當前未被覆蓋的州)的最大數目,理解類似於氣泡排序中的當前最大值
    for station,states in stations.items():#遍歷上面的廣播臺覆蓋模型,station對應廣播臺,states對應該廣播臺覆蓋的所有州
        covered = states_needed & states#求當前還未覆蓋的州與此廣播臺覆蓋的州的交集,便於後面求出當前覆蓋的州最多的廣播臺
        if(len(covered)>len(states_covered)):#如果當前州覆蓋的還未覆蓋的州數目大於此輪迴圈覆蓋最大的州數
            best_station = station#更新當前覆蓋最多未覆蓋州數目的廣播臺
            states_covered = covered#更新當前覆蓋的州
    states_needed -= states_covered#當前未被覆蓋的州
    final_stations.add(best_station)#將被選擇的州填入最終的廣播臺集合

結果如下:

print(final_stations)#列印最終選擇的廣播臺

這裡按照演算法,填入final_stations的順序應該是:kone,ktwo,kthree,kfive

(由於python的set集合會自動排序,故輸出結果按照上圖所示)