最短路徑純貪心演算法。

2022-03-13 17:28:27 字數 4847 閱讀 3231

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)

已知最短路徑

00->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  **如下(**可讀性一般)

struct

minroads

;int

main()

;

struct minroads minrd[7];//

初始化最短路徑陣列

int i=0

;

for(i=0;i<7;i++)

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

)

else

if(newshort<=temp_short)}}

}}inti_copy;

for(i_copy=0;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(

"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貪心演算法最短路徑 最短路徑純貪心演算法。

dijkstra演算法,書上其實說的很簡潔,仔細看,仔細思考是會理解的.但要先理解幾條引論和推理.而自己思考的思路在不需要任何推理只從貪心思路出發,和dijkstra有所不同,但本質一樣,那麼自己按照理解,試著慢慢講下.一,問題 從某個源點,到其他各點的最短路徑.注意,不要想成某乙個點,到某個點的最...

貪心演算法《最短路徑》

題目大意 存在幾個城市1 n 每個城市任意連向其他城市。並且,路程也是不盡相同的。若從乙個城市出發,去各個城市,則去各個城市每乙個城市的最短路程計算出來。如下是幾個城市的地圖 題目分析 乙個城市可能有多個路徑,但是尋找最小的路徑卻不容易。演算法 貪心演算法 從1城市出發,到達4和5城市最小路徑的充分...

python貪心演算法最短路徑 貪心演算法《最短路徑》

題目大意 存在幾個城市1 n 每個城市任意連向其他城市。並且,路程也是不盡相同的。若從乙個城市出發,去各個城市,則去各個城市每乙個城市的最短路程計算出來。如下是幾個城市的地圖 題目分析 乙個城市可能有多個路徑,但是尋找最小的路徑卻不容易。演算法 貪心演算法 從1城市出發,到達4和5城市最小路徑的充分...