dijkstra演算法,書上其實說的很簡潔,仔細看,仔細思考是會理解的.但要先理解幾條引論和推理.
而自己思考的思路在不需要任何推理只從貪心思路出發,和dijkstra有所不同,但本質一樣,那麼自己按照理解,試著慢慢講下.
一,問題:
從某個源點,到其他各點的最短路徑.
注意,不要想成某乙個點,到某個點的最短路徑.這樣的話不太好推導出思路。
某個源點,到其他各點的最短路徑.這樣的思路反而好推導出,反正所有點都計算出來了。某點到某點就是其中一條而已。,
二,分析.
先拋棄書中所有關於最短路徑的引理,定理,公理....
先看圖.
要找到從0點.到所有點的最短路徑.
假如,小明,站在0點.他很渴,天氣很熱,再不喝水要渴死,而每個其他點,都有一瓶水,點和點之間的交通工具還不一樣,有的是汽車,有的還必須走路.
假設這裡的權值代表兩點之間所花費的時間,比如0 ~3中間的數字6, 表示.從0到3要6個小時的慢車.
開啟地圖一看,到底哪個是最短啊.他想喝3點的水,發現要9個小時. 居然比 先到2,再到4, 7個小時還長,那麼去4吧.你當小明傻啊.到了2點,不喝水,還去4點.
所以小明得到乙個常識,對於第一瓶水,需要中轉點而到達的目的點肯定不是花費時間最少的,最起碼可以喝那個中轉站的水.
直連的點話,看看哪個點花費的時間少. 1點最少,只要3個小時.
廢話少說,小明直接從0做車到1,花費3個小時,喝到了第一瓶水,剛喝完水,小明被時光機, 卟的一聲,居然傳回了0點.(因為我們要從0開始,找出到所有點的最短路徑,所以小明被傳送了.)
因為小明還是很渴,天氣依然很熱,再不喝水要渴死.
那麼下乙個最近的點在**?
小明開始思索, 1點是和0直連最近的.已經被我喝掉了.那麼捨去1點,第二近的直連點是不是最近的呢?
先看看.發現了是6點.要4個小時.
其他直連點先全部拋棄,因為這個時候6點是直連點最近的了.
還有沒有比4個小時更短的?有,是之前的1點,只要3個小時,但喝掉了.
小明思索一會,有答案了,唯一可能的是,如果原來1點,離它很近的地方有頂點.那麼有可能比6點近.
看看地圖,1可以到4和5.時間是5和8. 總時間就是 3+5和3+8.明顯比4個小時長.
小明馬上又坐車從0點到了6點.喝光水,毫無疑問, 卟的一聲小明被時光機,又傳回了0點.
不過有了上次的思考.
小明有了初步總結.
下乙個最近的可能是2種方案中找乙個
1)和0直連的點,但要除去1,和6.也就是和0直連的 第3近的點.
2)從最早的的1點出發,所能到達的點,雖然上次排除了,但說不定這次和第3近的點有的一拼.
正要查地圖的時候.小明突然想到. 6點是第二近的點.說不定從6點出發,也有比 直連第3近的點更短呢.
終於,小明整理出了乙個方案.
用乙個陣列minrd ,存放已知最短路徑.
用另外乙個陣列noget,存放 所有點 減去 所有最短路徑的終點.
每次從最短路徑minrd中,查詢每條最短路徑的終點. 再寫下這些終點,到 未曾到達的點的權直.再找出最小的.
這裡要想明白, 假如有一條最短路徑經過了好幾個點,如 0->1->3->6->7. 小明最後一次喝掉了7點的水,
也意味著,他之前喝掉了6點的水,也就是0->1->3->6是乙個最短路徑,
0->1->3->6->7是從0->1->3->6這個最短路徑,由6頂點和其他最短路徑的頂點通過殘酷的比較中選出 來的.
這其實就是最優路徑的的乙個引論,最短路徑,中間的路徑也是最短路徑.喝水喝出了引論.
不厭其煩的,我要寫下每次程式執行的過程.
1)第一次找水.
已知最短路徑
0 這個是原點,預設放入.
還未到達過的
1,2,3,4,5,6
只有乙個終點0. 從終點出發,和還未到達過的點組成弧,找到最斷的.
比較 v(0,1),v(0,2),,v(0,3),v(0,4),v(0,5),v(0,6)
0->1最短,加入到最短路徑集合中.
2)已知最短路徑
0->1
還未到達過的
2,3,4,5,6
第乙個最短路徑的終點是0.第二條最短路徑的終點是1
從終點0和1出發,和還未到達過的點組成弧,找到最斷的.
比較 v(0,2),,v(0,3),v(0,4),v(0,5),v(0,6),
v(1,2),v(1,3),v(1,4),v(1,5),v(1,6)
0->6 最短,加入到最短路徑集合中
3)已知最短路徑
0,0->1 第一次找到的.
0->6 第二次找到的.
還未到達過的
2,3,4,5
比較 v(0,2),,v(0,3),v(0,4),v(0,5)
v(1,2),v(1,3),v(1,4),v(1,5)
v(6,2),v(6,3),v(6,4),v(6,5)
最優路徑終點0,1,6,
0->6->5 和 0->2 一樣,
根據程式判斷順序,會加入其中乙個,下次查詢會加入另外乙個. 也可以修改程式,讓他們一次加入
c **如下(**可讀性一般)
structminroads
;intmain()
;struct minroads minrd[7];//初始化最短路徑陣列
int i=0;for(i=0;i<7;i++)
minrd[i].road=malloc(sizeof(int)*7);
minrd[i].road[0]=0;
minrd[i].cost=0;
minrd[i].length=0;
}int noget[7]=;//初始化未曾到達的頂點集合。
minrd[0].road[0]=0;//把源點自己(起點)作為第一條最短路徑加入最短路徑集合(包含1個頂。權直和為0)
minrd[0].length=1;
minrd[0].cost=0;
noget[0]=-1;//簡單的把到達的點,標記為-1,0加入就把索引為0的數值改為-1。當nouse的元素全部為-1。那就全部到達。
int get_count=1;//
//從每條已知的最短路徑出發,走一步看看。比較所有產生的新路徑,看看誰最短。//程式描述就是找出 ,minrd中,每個road的權直,加上,這條road的頂點到noget中所有頂點的權直中最小的。
while(get_count<7)
elseif(newshort<=temp_short)
temp_short=newshort;
temp_s=i_shortest;
tmep_d=i_noget;
}inti_copy;for(i_copy=0;i_copy
minrd[get_count].road[i_copy]=minrd[temp_s].road[i_copy];
minrd[get_count].road[i_copy]=tmep_d;
minrd[get_count].length=minrd[temp_s].length+1;
minrd[get_count].cost+=temp_short;
noget[tmep_d]=-1;
get_count++;
}inti_print;for(i=0;i<7;i++)
else{
printf("%d",minrd[i].road[i_print]);
printf("cost:%d",minrd[i].cost);
printf("\n");
結果:再次注意這裡
0->6->5.這條最優路徑找出來的話。上面必定有0->6這條最優路徑。
閉著眼睛想一下,0->6->5是最優的話,沒有理由,0—>6不是。如果0->6不是,而是0->x.那麼,0->x->5,肯定比0->6->5更短。
dijkstra(迪傑斯特拉),是每次加入一條最短路徑,那麼更新 每個未處理的點 到 最短路徑的頂點集合 的最短路徑直。 選出最小的那個直。
注意當加入第乙個原點的時候,本身的權直就相當於更新過一遍.
因為更新過,
能體現出動態調整的思路。
而我們的思路
體現的是貪心演算法的思路。省掉了更新的步驟,每次重新計算所有的點.所以導致比dijkstra運算量稍微大點。
不過自己推導出來,並能理解的,總感覺更親切。
下篇看看怎麼更容易理解的方式寫出dijkstra
幾年後翻回來看。其實自己的想出來的思路,完全正確。就是貪心思路。
而dijkstra是貪心+動態。當年用貪心想到就結束了。沒有繼續優化,儲存中間值,否則就是dijkstra演算法了。
誇獎一下自己很難嗎?比心。
python貪心演算法最短路徑 貪心演算法《最短路徑》
題目大意 存在幾個城市1 n 每個城市任意連向其他城市。並且,路程也是不盡相同的。若從乙個城市出發,去各個城市,則去各個城市每乙個城市的最短路程計算出來。如下是幾個城市的地圖 題目分析 乙個城市可能有多個路徑,但是尋找最小的路徑卻不容易。演算法 貪心演算法 從1城市出發,到達4和5城市最小路徑的充分...
貪心演算法《最短路徑》
題目大意 存在幾個城市1 n 每個城市任意連向其他城市。並且,路程也是不盡相同的。若從乙個城市出發,去各個城市,則去各個城市每乙個城市的最短路程計算出來。如下是幾個城市的地圖 題目分析 乙個城市可能有多個路徑,但是尋找最小的路徑卻不容易。演算法 貪心演算法 從1城市出發,到達4和5城市最小路徑的充分...
最短路徑純貪心演算法。
dijkstra演算法,書上其實說的很簡潔,仔細看,仔細思考是會理解的.但要先理解幾條引論和推理.而自己思考的思路在不需要任何推理只從貪心思路出發,和dijkstra有所不同,但本質一樣,那麼自己按照理解,試著慢慢講下.一,問題 從某個源點,到其他各點的最短路徑.注意,不要想成某乙個點,到某個點的最...