使用貪心演算法解決集合覆蓋問題

jeanron100發表於2018-04-06

使用貪心演算法解決集合覆蓋問題

在《演算法圖解》裡面有一個蠻有意思的小案例,背景是一個廣播節目,要讓全美的50個周的聽眾都能夠聽到,但是每個電臺可能覆蓋多個州,每在一個電臺播出就需要一筆費用,所以就是從成本的角度來看,怎麼儘可能在所有的州都播出,這是一個典型的集合覆蓋的問題,而且在我們的生活中算是比較典型。

比如我們先縮小範圍,指定5個州,那麼50個州也是同樣的演算法。

states_need = set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"]) # 傳入一個陣列, 它被轉換為集合

有的同學可能對這些州沒概念,這個簡稱就跟京代表北京,魯代表山東,甘代表甘肅一樣,細細一看,都是西部的一些州。

使用貪心演算法解決集合覆蓋問題

如何使用貪心演算法呢,就是選擇覆蓋儘可能多的州的電臺,然後逐步縮小範圍。那麼覆蓋面廣的州所對應的電臺就優先被選中,依次類推。

程式的實現是指定了一個集合states_need,裡面包含所有的州,每個電臺對應的州是通過初始化的陣列元素來實現的,按照一二三四五的順序來命名,當然實際上這種元素的排列set不是按照陣列名的順序,在這個場景裡是kfive,ktwo,kthree,kone,kfour

然後逐步縮小範圍來收斂,裡面比較特別的一點就是集合的運算,使用了 & ,得到的是交集,如果是並集是 |,差集是 -,

程式程式碼如下:

#!/usr/bin/env
 python# coding:utf-8states_need = 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"])print(stations)# 最終選擇的廣播臺集合final_stations = set()while 
states_need:best_station = Nonestates_covered = set()for station, 
states_for_station in stations.items():covered = states_need & 
states_for_station # 
求交集print("states_need:",states_need,"states_for_station:",states_for_station,"covered:",covered)if
 len(covered) > len(states_covered):best_station = 
stationstates_covered = coveredstates_need -= 
states_coveredfinal_stations.add(best_station)print("states_needed:",states_need,"best_station:",best_station,"final_stations:",final_stations)print("---")print("Final_stations:",final_stations)

為了方便除錯和得到一個迭代的結果,我加了幾處輸出日誌,工參考。

{'kfive':
 set(['ca', 'az']), 'ktwo': set(['mt', 'id', 'wa']), 'kthree': 
set(['ca', 'or', 'nv']), 'kone': set(['ut', 'id', 'nv']), 'kfour': 
set(['ut', 'nv'])}('states_need:', set(['wa', 'ut', 'ca', 'id', 'mt', 
'az', 'or', 'nv']), 'states_for_station:', set(['ca', 'az']), 
'covered:', set(['ca', 'az']))('states_needed:', set(['wa', 'ut', 'id', 
'mt', 'or', 'nv']), 'best_station:', 'kfive', 'final_stations:', 
set(['kfive']))---('states_need:', set(['wa', 'ut', 'id', 'mt', 'or', 
'nv']), 'states_for_station:', set(['mt', 'id', 'wa']), 'covered:', 
set(['mt', 'id', 'wa']))('states_needed:', set(['ut', 'or', 'nv']), 
'best_station:', 'ktwo', 'final_stations:', set(['ktwo', 
'kfive']))---('states_need:', set(['ut', 'or', 'nv']), 
'states_for_station:', set(['ca', 'or', 'nv']), 'covered:', set(['or', 
'nv']))('states_needed:', set(['ut', 'or', 'nv']), 'best_station:', 
'ktwo', 'final_stations:', set(['ktwo', 'kfive']))---('states_need:', 
set(['ut', 'or', 'nv']), 'states_for_station:', set(['ut', 'id', 'nv']),
 'covered:', set(['ut', 'nv']))('states_needed:', set(['ut', 'or', 
'nv']), 'best_station:', 'ktwo', 'final_stations:', set(['ktwo', 
'kfive']))---('states_need:', set(['ut', 'or', 'nv']), 
'states_for_station:', set(['ut', 'nv']), 'covered:', set(['ut', 
'nv']))('states_needed:', set(['ut', 'or', 'nv']), 'best_station:', 
'ktwo', 'final_stations:', set(['ktwo', 'kfive']))---('states_need:', 
set(['ut', 'or', 'nv']), 'states_for_station:', set(['ca', 'az']), 
'covered:', set([]))('states_needed:', set(['ut', 'or', 'nv']), 
'best_station:', None, 'final_stations:', set(['ktwo', None, 
'kfive']))---('states_need:', set(['ut', 'or', 'nv']), 
'states_for_station:', set(['mt', 'id', 'wa']), 'covered:', 
set([]))('states_needed:', set(['ut', 'or', 'nv']), 'best_station:', 
None, 'final_stations:', set(['ktwo', None, 
'kfive']))---('states_need:', set(['ut', 'or', 'nv']), 
'states_for_station:', set(['ca', 'or', 'nv']), 'covered:', set(['or', 
'nv']))('states_needed:', set(['ut']), 'best_station:', 'kthree', 
'final_stations:', set(['ktwo', 'kthree', None, 
'kfive']))---('states_need:', set(['ut']), 'states_for_station:', 
set(['ut', 'id', 'nv']), 'covered:', set(['ut']))('states_needed:', 
set(['ut']), 'best_station:', 'kthree', 'final_stations:', set(['ktwo', 
'kthree', None, 'kfive']))---('states_need:', set(['ut']), 
'states_for_station:', set(['ut', 'nv']), 'covered:', 
set(['ut']))('states_needed:', set(['ut']), 'best_station:', 'kthree', 
'final_stations:', set(['ktwo', 'kthree', None, 
'kfive']))---('states_need:', set(['ut']), 'states_for_station:', 
set(['ca', 'az']), 'covered:', set([]))('states_needed:', set(['ut']), 
'best_station:', None, 'final_stations:', set(['ktwo', 'kthree', None, 
'kfive']))---('states_need:', set(['ut']), 'states_for_station:', 
set(['mt', 'id', 'wa']), 'covered:', set([]))('states_needed:', 
set(['ut']), 'best_station:', None, 'final_stations:', set(['ktwo', 
'kthree', None, 'kfive']))---('states_need:', set(['ut']), 
'states_for_station:', set(['ca', 'or', 'nv']), 'covered:', 
set([]))('states_needed:', set(['ut']), 'best_station:', None, 
'final_stations:', set(['ktwo', 'kthree', None, 
'kfive']))---('states_need:', set(['ut']), 'states_for_station:', 
set(['ut', 'id', 'nv']), 'covered:', set(['ut']))('states_needed:', 
set([]), 'best_station:', 'kone', 'final_stations:', set(['ktwo', 
'kthree', None, 'kfive', 'kone']))---('states_need:', set([]), 
'states_for_station:', set(['ut', 'nv']), 'covered:', 
set([]))('states_needed:', set([]), 'best_station:', 'kone', 
'final_stations:', set(['ktwo', 'kthree', None, 'kfive', 
'kone']))---('Final_stations:', set(['ktwo', 'kthree', None, 'kfive', 
'kone']))

最後的結果是:ktwo,kthree,kfive,kone這四個電臺。

當然貪心演算法得到的不是精確的結果,即可能不是最優解,算是一種近似演算法,能夠基本得到的最優解,而且效率很高。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2152644/,如需轉載,請註明出處,否則將追究法律責任。

相關文章