1. 程式人生 > >python解決最短路徑問題:Floyd-Warshall演算法

python解決最短路徑問題:Floyd-Warshall演算法

昨晚做的華為實習生筆試題第三題的解答就涉及到最短路徑問題,今天查閱資料l,重新做了一下。

主要思路:

1.根據天氣狀況更新路線圖hmap

2.根據最新的路線圖hmap,運用最短路徑演算法Floyd-Warshall演算法,求得任意兩城市之間最短路徑所必須經過的城市,放在path矩陣中(A矩陣存放對應的權值)

3.然後編寫一個函式getRoutes(path,start,end),根據指定的起始點和終點獲得路徑。

程式碼:

#coding= utf-8
#最短路徑問題:能到X的所有城市(除去自身),找到時間最小對應的城市M,然後找5到M的時間最小對應的城市,不斷遞推
#大霧城市:不可從該城市出發,也不可到達該城市,對應行列時間為1000
#從城市5出發到達任意城市的最短時間對應的路徑,及

#根據大霧城市設定新的map,y中存放的為大霧城市列表
from collections import defaultdict
from heapq import *
'''
def dijkstra_raw(edges, from_node, to_node):
    g = defaultdict(list)
    for l,r,c in edges:
	g[l].append((c,r))
    q, seen = [(0,from_node,())], set()
    while q:
	(cost,v1,path) = heappop(q)
	if v1 not in seen:
	    seen.add(v1)
	    path = (v1, path)
            if v1 == to_node:
                return cost,path
            for c, v2 in g.get(v1, ()):
		if v2 not in seen:
		    heappush(q, (cost+c, v2, path))
    return float("inf"),[]


def dijkstra(edges, from_node, to_node):
    len_shortest_path = -1
    ret_path=[]
    length,path_queue = dijkstra_raw(edges, from_node, to_node)
    if len(path_queue)>0:
        len_shortest_path = length		## 1. Get the length firstly;
        ## 2. Decompose the path_queue, to get the passing nodes in the shortest path.
        left = path_queue[0]
	ret_path.append(left)		## 2.1 Record the destination node firstly;
	right = path_queue[1]
	while len(right)>0:
            left = right[0]
	    ret_path.append(left)	## 2.2 Record other nodes, till the source-node.
            right = right[1]
	    ret_path.reverse()	## 3. Reverse the list finally, to make it be normal sequence.
    return len_shortest_path,ret_path
'''
def setNewMap(y):
    t = [[0,2,10,5,3,1000],
            [1000,0,12,1000,1000,10],
            [1000,1000,0,1000,7,1000],
            [2,1000,1000,0,2,1000],
            [4,1000,1000,1,0,1000],
            [3,1000,1,1000,2,0]]
    if len(y) == 1 and y[0] == '0':
        return t
    #字串變為int
    for i in xrange(len(y)):
        y[i] = int(y[i])
    #對應城市的行變為1000
    for i in xrange(len(y)):
        t[y[i]-1] = [1000,1000,1000,1000,1000,1000]
    #對應城市的列變為1000
    for i in xrange(6):
        for j in y:
            t[i][j-1] = 1000
    return t

#根據最短路徑矩陣,輸出兩點之間對應的路線
def getRoutes(path,start,end): #最短路徑矩陣
    rts = [] #存放路線
    rts.append(start)
    i = start-1
    while path[i][end-1] != -1:
        rts.append(path[i][end-1]+1)
        i = path[i][end-1]
    rts.append(end)
    return rts
#求最短路徑:指定起點sn,終點en和地圖tmp
def shortestPath(tmp):
    A = tmp
    path= [] #存放到某點必須經過的路徑點
    for i in xrange(6):
        path.append([-1,-1,-1,-1,-1,-1])
    for k in xrange(6):
        for i in xrange(6):
            for j in xrange(6):
                if A[i][j] > A[i][k] + A[k][j]:
                    A[i][j] = A[i][k] + A[k][j]
                    path[i][j] = k
    print 'A:%s'%(A)
    print 'path:%s'%(path)
    return A,path

hmap = [[0,2,10,5,3,1000],
        [1000,0,12,1000,1000,10],
        [1000,1000,0,1000,7,1000],
        [2,1000,1000,0,2,1000],
        [4,1000,1000,1,0,1000],
        [3,1000,1,1000,2,0]]
'''
lines = [] #存放最短路徑
#目的城市
X = raw_input()
#大霧城市,多個大霧城市時以,分割
Y = []
while True:
    ins = raw_input()
    if not ins:
        break
Y = ins.split(',')

#更新當前路徑地圖
tmp = setNewMap(Y)
'''
Y = [4]
tmp = setNewMap(Y)
a,path = shortestPath(tmp)
rts = getRoutes(path,5,2)
print rts
執行結果:


這一個測試用例通過了。

總結:

分析問題,剖析出對應的演算法,稍加改造執行實現。

最短路徑演算法參考連結: