今天繼續看《啊哈,算法》,學到了Floyd-Warshall算法
剛開始突然給我出現了e[i][j] 與 e[i][1]+e[1][j] 比較然後哪個小就賦值給e[i][j]
根據開頭圖來繪製出下面的表格,像之前求出最短路徑使用深搜與廣搜的方法
這一次不用深搜與廣搜來解決最小路徑
舉個例子現在:
要求1->3的最小路徑,首先看圖
一種是直接到達目的地:4->3 是有12格
另一種是有中轉點:4->1->3 這裏路徑僅有11格
如何通過Floyd-Warshall思想得到呢
我們將4->1->3 分成 4->1 和1->3
此時我們將初始點到目標點設置爲i=4,j=3
4->1 指向的就是e[i][1]
1->3 指的就是 e[1][3]
這樣就形成了 if(e[i][j]>(e[i][1]+e[1][j])) e[i][j] = e[i][1]+e[1][j]
裏面的1就是每一行的第一位,到了這裏你是否會提問爲什麼要1呢,2,3,4行嘛
這裏其實只是舉個例子,有些點可能要根據2這個中轉點找到兩點之間最短路徑
例如上圖中的1->3 就需要頂點2來求出最短路徑
我們只需要用一個for(k=1;k<=n;k++) 然後加上判斷語句就能全部進行判定比較,來得到最小路徑
使用for的話,if(e[i][j]>(e[i][k]+e[k][j])) e[i][j] = e[i][k]+e[k][j],這裏的1就要改變成k了
一定要自己親手比對過去,纔好理解,這裏想說發明的人也忒聰明瞭,他的名字是RobertW.Floyd(羅伯特.費羅伊德)
下面上代碼:
#include <stdio.h>
int main()
{
int e[51][51];
int inf = 999999;
int n,m,a,b,c,i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
if(i==j)
e[i][j]=0;
else
e[i][j] = inf;
}
//給表格賦值
for(i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
e[a][b] = c;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
for(k=1;k<=n;k++)
if(e[i][j]>(e[i][k]+e[k][j]))
e[i][j]=e[i][k]+e[k][j];
for(i=1;i<=n;i++){
for(j=1;j<=n;j++)
printf("%d ",e[i][j]);
printf("\n");
}
return 0;
}
如何設置無窮大的值:
認爲無窮大與其他值相加得到一個大於正無窮的數是不被允許的話加兩個判斷條件:
if(e[i][k]<inf && e[k][j]<inf && e[i][j]>(e[i][k]+e[k][j]))
可以加羣一起討論交流:891507813