Dijkstra最短路径算法

按路径长度的递增次序,逐步产生最短路径的贪心算法

基本思想:首先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从顶点v 到其它各顶点的最短路径全部求出为止。

时间复杂度为O(n2)

算法流程:

  1. 首先选定源点1,建立邻接矩阵C[5] [5],初始化三个数组分别为D[n],P[n],S[n],分别用来存储从源点到对应点的最短距离和最短路径上到该序列节点的前序节点,以及是否已经找到最短路径。
  2. 开始遍历源点的出边,将邻接矩阵的第一行放入数组D,找出距离最小的节点序号2,将数组P中的P[2]置为1,因为2的前序节点为1。
  3. 以上一步骤找到的节点为起点,继续遍历其邻接点(此处为2),若C[1][2]+C[2][m]<D[m] 则将其替换进数组D中,并将数组P中的P[m]置为2,因为m最短路径上的前序节点为2,节点2的邻接点全部遍历完成后,再从数组D中找出值最小且未被选中过的节点
  4. 重复以上步骤3,直到所有点都已经加入到数组S中。

程序实现:

public class Dijikstra extends Strategy {// open表Map<Integer, Node> open = new HashMap<>();// close表Map<Integer, Node> close = new HashMap<>();// 动作列表int[][] motion = get_motion();@Overridepublic List<Location> nextstep(Location start, Location work) {Node startnode = new Node(start.getX(), start.getY(), 0, -1);Node worknode = new Node(work.getX(), work.getY(), 0, -1);// 将起点放入open表open.put(cal_grid_index(startnode), startnode);// 向起点的上下左右四个方向扩展while (true) {// 与Astar算法不同 A*算法含有启发式函数 可以保证更快找到目标点// 但A*算法有可能永远无法找到目标点// Dijikstra算法虽然较慢 会遍历全部方向的点 但一定可以找到一条到目标点的路径// 找到map中节点cost最小的元素int temp_cost = Integer.MAX_VALUE;int current_id = 0;Node current = null;for (Map.Entry<Integer, Node> entry : open.entrySet()) {int current_cost =entry.getValue().cost + cal_Manhattan_distance(entry.getValue(), worknode);if (current_cost < temp_cost) {current_id = entry.getKey();temp_cost = current_cost;current = entry.getValue();}}// 判断是否找到目标点if (current.x == work.getX() && current.y == work.getY()) {System.out.println("找到目标点!");worknode.pind = current.pind;worknode.cost = current.cost;break;}// 移除open表中的current节点for (Iterator<Integer> iterator = open.keySet().iterator(); iterator.hasNext();) {Integer key = iterator.next();if (key == current_id) {iterator.remove();}}// 将current节点放入close表中close.put(current_id, current);for (int i = 0; i < motion.length; i++) {Node node = new Node(current.x + motion[i][0], current.y + motion[i][1],current.cost + motion[i][2], current_id);int node_id = cal_grid_index(node);// 该节点不能被扩展if (!verify_node(node)) {continue;}// 该节点已被确认过if (close.containsKey(node_id)) {continue;}// 将新扩展节点放入open表中if (!open.containsKey(node_id)) {open.put(node_id, node);} else {// 更新open表if (open.get(node_id).cost > node.cost) {open.put(node_id, node);}}}}open.clear();return cal_final_path(worknode, close);}/*** 根据终点回溯计算最短路径* * @param worknode* @param close* @return*/private List<Location> cal_final_path(Node worknode, Map<Integer, Node> close) {List<Location> ans = new ArrayList<>();int pind = worknode.pind;int i = 0;while (pind != -1) {// System.out.println(i);Node node = close.get(pind);Location location = new Location(node.x, node.y);ans.add(location);pind = node.pind;}return ans;}/*** 计算曼哈顿距离* * @param now* @param end* @return*/private int cal_Manhattan_distance(Node now, Node end) {return Math.abs(now.x - end.x) + Math.abs(now.y - end.y);}/*** 判断节点是否合理 1. 是否超出范围 2. 是否遇到货柜* * @param node* @return*/private boolean verify_node(Node node) {Container[][] map = ContainerMap.getMap();if (node.x < 0 || node.x >= ContainerMap.N || node.y < 0 || node.y >= ContainerMap.N) {return false;}if (map[node.x][node.y] != null) {return false;}return true;}/*** 计算栅格地图中的线性坐标* * @param node* @return*/private int cal_grid_index(Node node) {return node.y * ContainerMap.N + node.x;}/*** 定义动作及其代价 motion = {dx, dy, cost}* * @return*/private int[][] get_motion() {int[][] motion = {{1, 0, 1}, {0, 1, 1}, {-1, 0, 1}, {0, -1, 1}};return motion;}
}

A*算法

利用A*算法在拓扑地图上实现的路径规划:
关键:代价函数

  • 对于任意节点n
    • g(n)=从树根到n的代价
    • h*(n)=从n到目标节点的优化路径的代价
    • f*(n)=g(n) + h*(n)是节点n的代价
  • 估计h*(n)
    • 使用任何方法去估计h*(n), 用h(n)表示h*(n)的估计
    • h(n) <= h*(n)总为真
    • f(n)=g(n)+h(n) <= g(n)+h*(n)=f*(n)定义为n的代价




利用A*算法在栅格地图上实现的路径规划:
A*算法的核心思想是通过设置代价函数对未遍历点进行筛选,使搜索方向更偏向目标点,缩小搜索范围,进而提升搜索速度。公式f(n)=g(n)+h(n)是路径成本表达式。其中,f(n)为起点P—遍历中间点n—目标点g的路径总成本;g(n)为起点P—遍历中间点n之间的实际路径成本;h(n)为遍历中间点n—目标点Q的预估路径成本。寻找到最优解的条件是f(n)尽可能接近起点P到目标点Q的真实路径成本,此时搜寻到的点都是最短路径的过程点。由于遍历中间点n的g(n)值己知,因此只能提升h(n)的估计准确性,根据AGV在作业环境中只有“上下左右”四个行走方向,所以选取 h(n) = |Xn - XQ|+|Yn - YQ| (即曼哈顿距离),
算法流程描述如下:
(1)新建两个列表用作路径数据点存储:open list和close list,open list初始默认包含路径起点;
(2)计算与起点相邻的节点的f(n),按数值大小进行排序,f(n)最小的节点m转移到close list作为当前最优路径过程点,其余点留在open list中做备选点。
(3)若m为目标点,则停止搜索,并输出最优路径结果,否则继续;
(4)计算遍历中间栅格点m的所有相邻栅格点的f(n),若相邻节点n未加入open list,及时添加,并令g(n) = g(m) + d(m,n),此时n的父节点为m;若相邻点n在open list中,当g(n) > g(m) + d(m,n)时,更新g(n) = g(m) + d(m,n),设置n的父节点为m;
(5)遍历完所有备选点后重复步骤(2)-(4),直到目标点Q出现在open list中,搜索结束,按进入closed list的先后顺序输出中的节点栅格序列,该序列即为最优路径。

程序实现:

public class Astar extends Strategy {// open表Map<Integer, Node> open = new HashMap<>();// close表Map<Integer, Node> close = new HashMap<>();// 动作列表int[][] motion = get_motion();@Overridepublic List<Location> nextstep(Location start, Location work) {Node startnode = new Node(start.getX(), start.getY(), 0, -1);Node worknode = new Node(work.getX(), work.getY(), 0, -1);// 将起点放入open表open.put(cal_grid_index(startnode), startnode);// 向起点的上下左右四个方向扩展while (true) {if (open.size() == 0) {System.out.println("open表空!查找失败!");break;}// 找到map中节点cost最小的元素int temp_cost = Integer.MAX_VALUE;int current_id = 0;Node current = null;for (Map.Entry<Integer, Node> entry : open.entrySet()) {int current_cost =entry.getValue().cost + cal_Manhattan_distance(entry.getValue(), worknode);if (current_cost < temp_cost) {current_id = entry.getKey();temp_cost = current_cost;current = entry.getValue();}}// 判断是否找到目标点if (current.x == work.getX() && current.y == work.getY()) {System.out.println("找到目标点!");worknode.pind = current.pind;worknode.cost = current.cost;break;}// 移除open表中的current节点for (Iterator<Integer> iterator = open.keySet().iterator(); iterator.hasNext();) {Integer key = iterator.next();if (key == current_id) {iterator.remove();}}// 将current节点放入close表中close.put(current_id, current);for (int i = 0; i < motion.length; i++) {Node node = new Node(current.x + motion[i][0], current.y + motion[i][1],current.cost + motion[i][2], current_id);int node_id = cal_grid_index(node);// 该节点不能被扩展则查找下一个节点if (!verify_node(node)) {continue;}// 该节点已被确认过则查找下一个节点if (close.containsKey(node_id)) {continue;}// 将新扩展节点放入open表中if (!open.containsKey(node_id)) {open.put(node_id, node);} else {// 更新节点的代价if (open.get(node_id).cost > node.cost) {open.put(node_id, node);}}}}open.clear();return cal_final_path(worknode, close);}/*** 根据终点回溯计算最短路径* * @param worknode* @param close* @return*/private List<Location> cal_final_path(Node worknode, Map<Integer, Node> close) {List<Location> ans = new ArrayList<>();int pind = worknode.pind;int i = 0;while (pind != -1) {// System.out.println(i);Node node = close.get(pind);Location location = new Location(node.x, node.y);ans.add(location);pind = node.pind;}return ans;}/*** 计算曼哈顿距离* * @param now* @param end* @return*/private int cal_Manhattan_distance(Node now, Node end) {return Math.abs(now.x - end.x) + Math.abs(now.y - end.y);}/*** 判断节点是否合理 1. 是否超出范围 2. 是否遇到货柜* * @param node* @return*/private boolean verify_node(Node node) {Container[][] map = ContainerMap.getMap();if (node.x < 0 || node.x >= ContainerMap.N || node.y < 0 || node.y >= ContainerMap.N) {return false;}if (map[node.x][node.y] != null) {return false;}return true;}/*** 计算栅格地图中的线性坐标* * @param node* @return*/private int cal_grid_index(Node node) {return node.y * ContainerMap.N + node.x;}/*** 定义动作及其代价 motion = {dx, dy, cost}* * @return*/private int[][] get_motion() {int[][] motion = {{1, 0, 1}, {0, 1, 1}, {-1, 0, 1}, {0, -1, 1}};return motion;}
}

[算法]-最短路径算法总结相关推荐

  1. 神经网络最短路径算法,最短路径算法的原理

    节约里程法求解最短路问题 你只要记住2点之间直线最短.节约里程法是用来解决运输车辆数目不确定的问题的最有名的启发式算法.1.节约里程法优化过程分为并行方式和串行方式两种. 核心思想是依次将运输问题中的 ...

  2. 【老生谈算法】matlab实现最短路径算法——最短路径算法

    最短路径算法-matlab程序 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 序号 文档(点击下载) 本项目文档 [老生谈算法]最短路径算法-matlab程序.doc 2.算 ...

  3. 【算法】弗洛伊德算法 最短路径算法

    文章目录 1.概述 2.图解 2.1 图示 2.2 弗洛伊德算法的步骤: 3.代码 1.概述 弗洛伊德(Floyd)算法介绍 和Dijkstra算法一 样,弗洛伊德(Floyd)算法也是一种用 于寻找 ...

  4. 弗洛伊德算法——最短路径算法

    弗洛伊德(Floyd)算法介绍 和Dijkstra算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算 ...

  5. 弗洛伊德算法-----最短路径算法(一)

    学习此算法的原因:昨天下午遛弯的时候,碰到闺蜜正在看算法,突然问我会不会弗洛伊德算法?我就顺道答应,然后用了半个小时的时间,学习了此算法,并用5分钟讲解给她听,在此也分享给各位需要的朋友,让你们在最短 ...

  6. 【算法】迪杰斯特拉算法 最短路径算法

    文章目录 1.概述 1.1 算法介绍 1.2 算法过程 2.代码 1.概述 太难了:https://www.bilibili.com/video/BV1E4411H73v?p=178 应用场景如下 战 ...

  7. 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson,无一幸免

    文章出自:http://dsqiu.iteye.com/blog/1689163 最短路径算法--Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson,无一幸免 本 ...

  8. 我是怎么使用最短路径算法解决动态联动问题的

    省市县三级联动问题相信大家都耳熟能详了,选择市下拉选项依赖于省,同样的选择县下拉选项依赖于市.把省市县抽象成三个节点A(省),B(市),C(县),它们的关系如下图(1).假如把这个联动问题复杂化一点如 ...

  9. (最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法

    一.floyd 1.介绍 floyd算法只有五行代码,代码简单,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3),可以求多源最短路问题. 2.思想: Floyd算法的基本思想如下:从任意 ...

最新文章

  1. CentOS 7磁盘格式化
  2. Spring+SpringMVC+Mybatis整合
  3. Python正则匹配HTML,python正则匹配html标签_Python爬虫常用正则表达式及HTML网页标签分析总结...
  4. 杭电2028--Lowest Common Multiple Plus
  5. boost::range模块replaced相关的测试程序
  6. matplotlib设置多个图例横向水平放置
  7. ReportViewer教程(15)-矩阵报表-6
  8. Flink的并行度和Kafka的partition的结合
  9. 随想录(easyx开发上位机)
  10. 英语总结系列(二十九):好好学英语
  11. jstl标签库基础教程及其使用代码
  12. 《Perl语言入门》学习笔记
  13. 【面试】AI算法工程师---面试题!(第二部分:AI部分)
  14. Android 屏蔽Power键 Home键
  15. 括号配对检测python123_括的意思
  16. EMQ X 存储消息到 MySQL 数据库
  17. 小狗钱钱跟着钱钱学理财
  18. 组内相关系数intraclass correlation(ICC)
  19. xv6 CPU alarm
  20. BPF学习笔记(六)-- 使用bpf实现xdp的例子

热门文章

  1. 算法学习--水洼的数量
  2. EBS R12.2.6 克隆超详细操作手册
  3. TP-LINK 5200H无线USB网卡ubuntu驱动
  4. 今天我们来聊聊 UI 组件库推广一年有余遇到的困境吧
  5. 【DC-DC】AP5193 DC-DC宽电压LED降压恒流驱动器 LED电源驱动IC
  6. C++读取ini格式配置文件
  7. C++:面向对象(总结+补习)
  8. 5款功能强大的国产软件,大幅提升你的工作效率,可免费使用
  9. partial 函数
  10. 堆排序(完全二叉树)最后一个非叶子节点的序号是n/2-1的原因