python數據結構與算法之問題求解實例
關於問題求解,書中有一個實際的案例。
上圖是一個交叉路口的模型,現在問題是,怎麽安排紅綠燈才可以保證相應的行駛路線互不交錯。
第一步,就是把問題弄清楚。
怎麽能讓每一條行駛路線不沖突呢?
其實,就是給所有的行駛路線分組(這樣保證了安全問題,不會撞車)。
並且,所做的分組應該盡可能大一些,用以提高路口的通行效率(經濟問題,如果一個組一條路線,雖然不會撞車,但是等待的時間會很長)。
有了上面的最大化分組的想法。那麽就進一步將問題具體化。
這個路口有13個可供行駛的方向:AB,AC,AD,BA,BC,BD,DA,DB,DC,EA,EB,EC,ED。
現在問題就轉化為,給這13條路線分組,使其各個組不沖突,並且最大化組中的成員。
在書中引出了一個沖突圖,用來表示各個路線的沖突。
其中圖中元素稱之為頂點,連線稱之為邊或者弧。相互之間有邊的頂點稱為鄰接頂點。
安全分組就變成了另外一種說法,為沖突圖中的頂點確定一種分組,保證屬於同一分組的所有頂點互不鄰接。
到了這裏就完了第一步,將問題嚴格化。
第二步,就是進行數據結構與算法設計
使用什麽樣的數據結構來表示沖突中的形式路線,又用哪種算法來計算分組。
書中首先提到了一個最佳著色算法,其實就是著名的四色問題,這個算法能找到最佳的分組方案。但是由於算法代價太高,效率不高。因此著重介紹了一個更為簡單的算法。
那就是貪心法。它的基本想法是這樣的:利用當時掌握的信息,盡可能地向得到解的方向前進,知道不能繼續再換一個方法。
那麽在這個例子中的具體表現就是:就是確定一個分組,這個分組裏的成員互相都不鄰接,也就是說不能沖突。當這個分組完成之後,再確定下一個分組。
按照這個方法,上面的例子分組就是:
{AB,AC,AD,BA,DC,ED}
{BC,BD,EA}
{DA,DB}
{EB,EC}
算法的偽代碼如下:
輸入:圖G #記錄著圖中頂點連接的關系
集合verts保存G中所有的頂點 #建立初始狀態
設置集合groups為空集 #記錄得到的分組,元素是頂點集合
while 存在未著色頂點:
選一種新的顏色
在未著色頂點中給盡量多的無連邊的點著色(構建一個分組)
記錄新著色的頂點組
python偽代碼:
new_group = 空集
for v in verts:
if v 與new_group集合中的頂點都不相連:
將v從verts中取出
new_group.add(v)
循環結束時,new_grouo是可以用一種新的顏色著色的頂點集合
第三步,編寫代碼。
其實,上面的偽代碼已經接近於具體程序了。只是還有一些細節需要考慮。
1、如何表示顏色。這個簡單,用整數就可以。其實,用不用顏色表示都可以,只要將每個分組分開即可。這裏采用二元組來表示,一個表示顏色,一個表示分好的組。、
2、如何記錄分組。可以用一個集合來記錄,也就是groups是集合的集合。
3、如何表示圖結構?這個比較難,是後面的內容,這裏先略過。
由此可得出python的代碼:
def coloring(G)
color = 0
groups = set()
verts = vertices(G) #用來獲取所有的頂點
while verts:
new_groups = set()
for v in list(verts):
if not_adjacent_with_set(v, newgroup, G):
new_group.add(v)
verts.remove(v)
groups.add((color, new_group))
color += 1
return grous
第四步,測試代碼,尋找一些邊界例子測試代碼的嚴謹性以及邏輯性。
由於,這裏並不是一個完整的項目,而且這個例子比較簡單,就簡單分析討論一下,應該註意的幾個問題。
1、它的解唯一嗎?
其實,大致觀察一下,就會發現,上面的算法只能給出一個恰好的解。例如,下面的分組也是一個解
{AB,EB,EC}
{AC,AD,BC,}
{BA,BD,DB,ED}
{DA,DC,EA}
其實,經過分析。對於BA、DC、ED三個頂點,將它們放在任何一個分組都是可以的。因為它們不跟任何一個頂點相連,也就是公認的無害右轉彎。對於這個設計具體得看對於沖突概念的定義。
2、再次回顧一下算法的實現跟原來的問題是否相符
原來的問題是怎麽分配,各個路線才能不沖突。
而上面的算法給出了一種不沖突的方法,但並不是最優的解。比如:上面的算法中每個分組都頂點都不允許重復,也就是各個分組互不相交。但真正的問題並沒有這個要求。無害的右轉彎就與各個分組都不沖突,完全可以都分配在各個分組裏面。使其得到下面的分配:
{AB,AC,AD,BA,DC,ED}
{BC,BD,EA,BA,DC,ED}
{DA,DB,BA,DC,ED}
{EB,EC,BA,DC,ED}
這樣就會將分組盡可能地擴充,使其經濟效率更高(這個分組還可以繼續擴充為{DA,DB,BA,DC,ED,AD})。
當然,這個問題還會有其他的一些具體的問題,這裏就不討論了。作者主要是用一個例子來帶我們分析了一下,如何將生活中的實際問題,一步一步通過分析設計,最終得到一個完整的正確的效率高的計算機程序。
python數據結構與算法之問題求解實例