疫情缘由,公司干脆利落地把咱们业务组给裁啦,我也光荣地成为了一个下岗待业的老程序员。程序员
开发工做很差找啊,毕竟都要35岁如下的,因此我寻思再就业能够换个方向,好比说送外卖,再怎么说X团、X了么也是大厂嘛~算法
既然下定决心,第一步就是要武装头脑,拿起理论的武器,送外卖第一要务是什么?快!!天下武功,惟快不破。速度速度速度,重要的事情说三遍。ide
如何快速抵达商家,再快速将饭菜送到顾客手中,少跑路是关键——这就是最短路径问题,下面我就描述一下,我是如何使用Dijkstra算法结合回龙观的地图来计算最短路径的。工具
选回龙观的缘由:一、回龙观的道路状况很好,基本上是横平竖直;二、我家就在这,送外卖在家附近送,路熟。学习
回龙观的地图如上,由于是作实验,就选取了部分区域:北起回南北路,南至同成街;东起G6辅路,西至文化东路。测试
以前个人两篇描述最短路径算法的文章中,使用的图都是相似:3d
若是用在地图上,就有些不合适,由于不太好体现真实状况,以下图:code
在示意图中,两点之间只会有一条边A,但现实中,两地的路线有B、C两条,因此为了让示意图更贴合显示,就有了变种图:blog
每个方块表明一个顶点,两个相邻顶点的边权重视为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,则较短路径应为第二条。
我使用地图的测距工具获得了 如下不怎么精确的距离:
以路口为点,两点之间的距离如上图,单位千米。
我假设每个方块都表明100*100米,那么示意图以下:
不要问为何是圆而不是说好的方块,由于圆比方块好画~~~
也请忽视圆的大小不一,单位固定都是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){ 一、构建到某一顶点最短路径的起点Map——parentMap 二、构建已处理最短路径顶点Map——s;构建待处理最短路径顶点Map——w 三、构建(顶点A-顶点B:边权)的Table——ppw 四、遍历全部顶点{ 4.1将w转为优先队列,并取出最小值的顶点,将其从w挪入s,并以此为顶点(设为Key1)计算其相邻顶点的权重。 4.2若是取出的最小值顶点就是终点,且最小值不是无穷大(在程序中用Integer.MAX_VALUE代替),说明已经计算到终点,不须要计算后面的点,直接跳出循环。 4.3内循环遍历全部顶点(设为Key2),根据Key1-Key2从ppw中取出权重。 4.4若是ppw取出为null,说明两顶点间无路径。 4.5根据Key一、Key2的值、边权对Key2进行松弛操做。 } }
至此,核心代码已经完成,后续还有输入骑手、商家、顾客,调用核心代码,并输出路径的方法等,在此再也不赘述。
如下为测试结果。
假设骑手在回龙观西大街与育知东路的交叉口(即24),商家在北京华联同成街店(即177),顾客在天露园二区北门(即89),计算的结果以下:
以商家到顾客路线为例,地图给出的路径如图:
程序给出的路径:
基本还算一致。
固然这只是一个很简陋的程序,有许多实际问题没有考虑,好比出行方式、拥堵、红绿灯、单行道、禁行路段、立体交通等。
例如点26,同成街与育知东路交叉点,这实际上是个桥,若是从175到236,开车的话是不可能走175-26-236路线的,必须绕一圈。
这篇文章其实也只是记录一下我的将理论与实际相结合的学习过程,疏漏错误在所不免。
好了,不说了,仅有理论的指导仍是不够的,我去升级装备了。