代码随想录算法训练营第六十四天|Floyd 算法、A * 算法、最短路算法总结

97. 小明逛公园

在这里插入图片描述
在这里插入图片描述

Floyd 算法

Floyd-Warshall算法是一种用于求解图中所有节点对之间最短路径的经典算法。它的时间复杂度为O(n^3),适用于节点数量不多(通常不超过几百个)的密集图。该算法不仅能处理带权有向图,还能处理带权无向图。

核心思想:动态规划
Floyd-Warshall算法通过引入中间节点的方式,逐步更新节点对之间的最短路径。先遍历中间节点k的原因是为了确保每次更新节点对(i, j)的路径时,都已经考虑过通过所有之前的节点(从1到k-1)作为中间节点的可能性

算法步骤:

1.	初始化:将每个节点对之间的初始距离存储在一个二维数组grid中。如果存在直接边,则将grid[i][j]设为对应的边权重;如果不存在,则设为一个大值(通常表示无穷大),自身到自身的距离设为0。
2.	动态规划:
•	通过引入中间节点k逐步更新最短路径。
•	三重循环遍历每个节点对,并检查通过每个中间节点k是否能找到更短的路径。
•	具体地,检查dist[i][j]是否大于dist[i][k] + dist[k][j],如果是则更新dist[i][j]为后者。
3.	输出结果:完成所有更新后,dist[i][j]中存储的就是节点i到节点j的最短路径长度。

代码实现:

 public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 读取节点数n和边数m
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        
        // 初始化grid数组,表示节点间的最短路径
        int[][] grid = new int[n + 1][n + 1];
        
        // 将grid数组中的所有值初始化为较大值(表示无穷大)
        for (int[] ints : grid) {
            Arrays.fill(ints, 10005);
        }

        // 自身到自身的距离设为0
        for (int i = 1; i <= n; i++) {
            grid[i][i] = 0;
        }

        // 读取边的信息并更新grid数组
        for (int i = 0; i < m; i++) {
            int s = scanner.nextInt(); // 起点
            int t = scanner.nextInt(); // 终点
            int val = scanner.nextInt(); // 边的权重
            grid[s][t] = val; // 初始时刻的最短路径
            grid[t][s] = val; // 无向图,双向更新
        }

        // 读取查询的计划数
        int q = scanner.nextInt();
        int[][] plans = new int[q][2];
        
        // 读取查询计划的起点和终点
        for (int i = 0; i < q; i++) {
            plans[i][0] = scanner.nextInt();
            plans[i][1] = scanner.nextInt();
        }

        // 使用Floyd-Warshall算法进行多阶段动态规划求解最短路径
        for (int k = 1; k <= n; k++) {
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    // 更新最短路径
                    grid[i][j] = Math.min(grid[i][j], grid[i][k] + grid[k][j]);
                }
            }
        }

        // 输出每个查询计划的结果
        for (int[] plan : plans) {
            int start = plan[0];
            int end = plan[1];
            int res = grid[start][end];
            // 如果距离还是初始的较大值,表示两点之间无路径
            System.out.println(res == 10005 ? -1 : res);
        }
    }

127. 骑士的攻击在这里插入图片描述

A * 算法

A*算法是一种用于图搜索的启发式算法,广泛应用于路径规划和导航等领域。它结合了Dijkstra算法的最短路径搜索和启发式搜索策略,能够高效地找到从起点到终点的最短路径。

A*算法的基本思路:

A*算法通过以下三个值来进行路径搜索:

1.	G值:从起点到当前节点的实际消耗。
2.	H值:从当前节点到终点的预估消耗(启发式函数)。
3.	F值:F = G + H,表示经过当前节点的总消耗。

算法步骤

1.	初始化:
•	将起点加入到开放列表(open list)中,并初始化其G、H和F值。
•	开放列表用于存储待检查的节点,关闭列表(closed list)用于存储已检查的节点。
2.	选择当前节点:
•	从开放列表中选择F值最小的节点作为当前节点。如果当前节点是终点,则搜索结束。
•	否则,将当前节点从开放列表移除并加入关闭列表。
3.	处理相邻节点:
•	对于当前节点的每个相邻节点,计算其G、H和F值:
•	如果相邻节点在关闭列表中,则跳过。
•	如果相邻节点不在开放列表中,则将其加入开放列表,并设置其父节点为当前节点。
•	如果相邻节点已经在开放列表中,但通过当前节点到达相邻节点的G值更小,则更新相邻节点的G值和父节点。
4.	重复步骤2和步骤3,直到找到终点或开放列表为空(表示无解)。

启发式函数

启发式函数H的选择非常重要,直接影响A*算法的性能。常用的启发式函数有:

•	曼哈顿距离:适用于棋盘格上的移动,不允许对角线移动。
•	欧几里得距离:适用于允许任意方向移动的情况。
•	切比雪夫距离:适用于允许八方向(包括对角线)移动的情况。

最短路算法总结

在这里插入图片描述

如何选用?

高要求:
在这里插入图片描述

这个过程中考虑点还是边看是稠密图还是稀疏图

低要求: 会个Floyd和朴素版本Bellman-Ford以及变种即可

  1. 多源就用Floyd-Warshall算法
  2. 单源就用(朴素版本Bellman-Ford算法 + 负权回路检测) 版本
    • 2.1 有限就用有限节点最短路径版本(朴素版本Bellman-Ford算法 + 负权回路检测 + 有限节点)版本
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值