被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

疫情原因,公司乾脆利落地把我們業務組給裁啦,我也光榮地成爲了一個下崗待業的老程序員。

開發工作不好找啊,畢竟都要35歲以下的,所以我尋思再就業可以換個方向,比如說送外賣,再怎麼說X團、X了麼也是大廠嘛~

既然下定決心,第一步就是要武裝頭腦,拿起理論的武器,送外賣第一要務是什麼?快!!天下武功,唯快不破。速度速度速度,重要的事情說三遍。

如何快速抵達商家,再快速將飯菜送到顧客手中,少跑路是關鍵——這就是最短路徑問題,下面我就描述一下,我是如何使用Dijkstra算法結合回龍觀的地圖來計算最短路徑的。

選回龍觀的原因:1、回龍觀的道路情況很好,基本上是橫平豎直;2、我家就在這,送外賣在家附近送,路熟。

被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣
回龍觀的地圖如上,因爲是做實驗,就選取了部分區域:北起回南北路,南至同成街;東起G6輔路,西至文化東路。

之前我的兩篇描述最短路徑算法的文章中,使用的圖都是類似:

被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

如果用在地圖上,就有些不合適,因爲不太好體現真實情況,如下圖:

被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

在示意圖中,兩點之間只會有一條邊A,但現實中,兩地的路線有B、C兩條,所以爲了讓示意圖更貼合顯示,就有了變種圖:

被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

每一個方塊代表一個頂點,兩個相鄰頂點的邊權重視爲1.

如上圖,其中藍色數字的方塊代表可通過的路,紅色英文的方塊代表不可通行,其頂點邊權組合應如下:

1-2-1,1-16-1

2-1-1,2-3-1

3-2-1,3-4-1,3-17-1

4-3-1,4-5-1

5-4-1,5-6-1

...... ......

18-17-1,18-19-1,18-20-1,18-21-1

假如以北店嘉園北區東門爲起點,即19,以龍回苑西門爲終點,即5.

可得最短路線爲19-18-21-7-6-5或19-18-17-3-4-5,再結合實際道路情況,例如擁堵程度、紅綠燈、單行路等,可得出相對較短的路線。

假設龍禧二街常年堵車,邊權設爲2,則較短路徑應爲第二條。

我使用地圖的測距工具得到了 以下不怎麼精確的距離:

被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

以路口爲點,兩點之間的距離如上圖,單位公里。

我假設每一個方塊都代表100*100米,那麼示意圖如下:

被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

不要問爲什麼是圓而不是說好的方塊,因爲圓比方塊好畫~~~

也請忽視圓的大小不一,單位固定都是100*100米。

接着我們上代碼。

首先我們必須構建頂點的邊權數據,類似1-45-1,1-74-1這種。

在這裏我採用了Guava裏的HashBasedTable結構,即Key1-Key2:Value。


Table<Integer, Integer, Integer> ppw = HashBasedTable.create();
ppw.put(1, 45, 1);
ppw.put(1, 74, 1);
ppw.put(45, 1, 1);
ppw.put(74, 1, 1);

在本圖裏,共有296個頂點,相關邊更多,純手工錄入會崩潰的,所以我寫了程序,根據輸入的頂點範圍生成相應的代碼。即便這樣也是很累人的。

接着實現Dijkstra算法。僞代碼如下,入參有兩個:起點,終點,


public void getShortestPath(Integer start, Integer end){
 1、構建到某一頂點最短路徑的起點Map——parentMap
 2、構建已處理最短路徑頂點Map——s;構建待處理最短路徑頂點Map——w
 3、構建(頂點A-頂點B:邊權)的Table——ppw
 4、遍歷所有頂點{
  4.1將w轉爲優先隊列,並取出最小值的頂點,將其從w挪入s,並以此爲頂點(設爲Key1)計算其相鄰頂點的權重。
  4.2如果取出的最小值頂點就是終點,且最小值不是無窮大(在程序中用Integer.MAX_VALUE代替),說明已經計算到終點,不需要計算後面的點,直接跳出循環。
  4.3內循環遍歷所有頂點(設爲Key2),根據Key1-Key2從ppw中取出權重。
  4.4如果ppw取出爲null,說明兩頂點間無路徑。
  4.5根據Key1、Key2的值、邊權對Key2進行鬆弛操作。
 }
}

至此,核心代碼已經完成,後續還有輸入騎手、商家、顧客,調用核心代碼,並輸出路徑的方法等,在此不再贅述。

以下爲測試結果。

假設騎手在回龍觀西大街與育知東路的交叉口(即24),商家在北京華聯同成街店(即177),顧客在天露園二區北門(即89),計算的結果如下:

被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

以商家到顧客路線爲例,地圖給出的路徑如圖:

被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

程序給出的路徑:

被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

基本還算一致。

當然這只是一個很簡陋的程序,有許多實際問題沒有考慮,比如出行方式、擁堵、紅綠燈、單行道、禁行路段、立體交通等。

例如點26,同成街與育知東路交叉點,這其實是個橋,如果從175到236,開車的話是不可能走175-26-236路線的,必須繞一圈。

這篇文章其實也只是記錄一下個人將理論與實際相結合的學習過程,疏漏錯誤在所難免。

好了,不說了,僅有理論的指導還是不夠的,我去升級裝備了。
被裁老程序員再就業計劃之我可以用Dijkstra算法在回龍觀送外賣

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章