【代码随想录训练营第42期 Day61打卡 - 图论Part11 - Floyd 算法与A * 算法
目录
一、Floyd算法与A * 算法
1、Floyd算法
思想
伪代码
2、 A * 算法
思想
伪代码
二、经典题目
题目一:卡码网 97. 小明逛公园
题目链接
题解:Floyd 算法
题目二:卡码网 127. 骑士的攻击
题目链接
题解:A * 算法(A-Star)
三、小结
一、Floyd算法与A * 算法
1、Floyd算法
思想
Floyd算法的基本思想是逐步迭代地考虑图中的所有顶点,并更新任意两点之间的最短路径长度。在每一步迭代中,算法检查所有顶点对(i,j),并通过当前考虑的顶点k,看是否能够找到一条从i到j的更短路径。具有能够找到图中任意两点间的最短路径的优势,适合解决多源最短路,即求多个起点到多个终点的多条最短路径。
Floyd算法核心思想是动态规划。
伪代码
function floydWarshall(weights, V):let dist be a V x V arrayfor i from 0 to V-1:for j from 0 to V-1:if i == j:dist[i][j] = 0else if there is an edge from i to j:dist[i][j] = weight of the edge from i to jelse:dist[i][j] = INFINITYfor k from 0 to V-1:for i from 0 to V-1:for j from 0 to V-1:if dist[i][k] + dist[k][j] < dist[i][j]:dist[i][j] = dist[i][k] + dist[k][j]return dist
2、 A * 算法
入门建议观看视频:【A*寻路算法详解 #A星 #启发式搜索】
思想
A算法(A-Star算法)是一种在图形平面上,有多个节点的路径中,寻找一条从起点到终点的最短路径的算法。它的设计思想主要结合了实际代价和启发式估计,以高效地搜索图形中的最优路径。
核心思想是将启发式搜索和最佳优先搜索结合起来,以寻找从起始点到目标点的最短路径。
伪代码
function A*(start, goal)open_list = priority_queue() // 优先队列,按f值排序start.g = 0start.h = heuristic(start, goal)start.f = start.g + start.hstart.parent = nullopen_list.add(start)while not open_list.is_empty()current = open_list.pop() // 取出f值最小的节点if current == goalreturn reconstruct_path(current)closed_list.add(current) // 将当前节点加入封闭列表for neighbor in neighbors(current)if neighbor in closed_listcontinuetentative_g = current.g + distance(current, neighbor)if neighbor not in open_list or tentative_g < neighbor.gneighbor.parent = currentneighbor.g = tentative_gneighbor.h = heuristic(neighbor, goal)neighbor.f = neighbor.g + neighbor.hif neighbor not in open_listopen_list.add(neighbor)return null // 没有找到路径function reconstruct_path(node)path = []while node is not nullpath.prepend(node)node = node.parentreturn path.reverse() // 反转路径以从起点到终点function heuristic(node, goal)// 返回从node到goal的启发式估计值
end functionfunction neighbors(node)// 返回node的邻居节点列表
end functionfunction distance(node1, node2)// 返回从node1到node2的实际距离
end function
二、经典题目
题目一:卡码网 97. 小明逛公园
题目链接
97. 小明逛公园 (kamacoder.com)
题目描述
小明喜欢去公园散步,公园内布置了许多的景点,相互之间通过小路连接,小明希望在观看景点的同时,能够节省体力,走最短的路径。
给定一个公园景点图,图中有 N 个景点(编号为 1 到 N),以及 M 条双向道路连接着这些景点。每条道路上行走的距离都是已知的。
小明有 Q 个观景计划,每个计划都有一个起点 start 和一个终点 end,表示他想从景点 start 前往景点 end。由于小明希望节省体力,他想知道每个观景计划中从起点到终点的最短路径长度。 请你帮助小明计算出每个观景计划的最短路径长度。
输入描述
第一行包含两个整数 N, M, 分别表示景点的数量和道路的数量。
接下来的 M 行,每行包含三个整数 u, v, w,表示景点 u 和景点 v 之间有一条长度为 w 的双向道路。
接下里的一行包含一个整数 Q,表示观景计划的数量。
接下来的 Q 行,每行包含两个整数 start, end,表示一个观景计划的起点和终点。
输出描述
对于每个观景计划,输出一行表示从起点到终点的最短路径长度。如果两个景点之间不存在路径,则输出 -1。
输入示例
7 3 2 3 4 3 6 6 4 7 8 2 2 3 3 4
输出示例
4 -1
提示信息
从 2 到 3 的路径长度为 4,3 到 4 之间并没有道路。
1 <= N, M, Q <= 1000.
题解:Floyd 算法
关键在于Floyd算法的实现,即:
使用三重循环来实现Floyd算法:
外层循环变量 k 代表中间节点,内两层循环变量 i 和 j 分别代表起点和终点。
在每一轮循环中,检查通过中间节点 k 从 i 到 j 的路径是否比当前已知的路径更短,如果是,则更新 grid[i][j]。
代码实现:
for (int k = 1; k <= n; k++) // k代表中间节点{for (int i = 1; i <= n; i++) // i代表起点{for (int j = 1; j <= n; j++) // j代表终点{grid[i][j] = min(grid[i][j], grid[i][k] + grid[k][j]); // 更新i到j的最短路径,如果通过k的路径更短,则更新}}}
完整代码如下:
#include <bits/stdc++.h>
using namespace std;int main()
{int n, m, p1, p2, val;cin >> n >> m;vector<vector<int>> grid(n + 1, vector<int>(n + 1, 10005)); // 创建一个二维向量grid来存储图的邻接矩阵,因为边的最大距离为10**4// 读取m条边的信息,并更新邻接矩阵for (int i = 0; i < m; i++){cin >> p1 >> p2 >> val;grid[p1][p2] = val;grid[p2][p1] = val; // 注意这里是双向图:需要考虑两个方向}// 开始 floyd 算法for (int k = 1; k <= n; k++) // k代表中间节点{for (int i = 1; i <= n; i++) // i代表起点{for (int j = 1; j <= n; j++) // j代表终点{grid[i][j] = min(grid[i][j], grid[i][k] + grid[k][j]); // 更新i到j的最短路径,如果通过k的路径更短,则更新}}}// 输出结果int Q, start, end;cin >> Q;while (Q--){cin >> start >> end;if (grid[start][end] == 10005) // 如果最短路径长度仍然是初始值,表示没有路径cout << -1 << endl;elsecout << grid[start][end] << endl;}return 0;
}
题目二:卡码网 127. 骑士的攻击
题目链接
127. 骑士的攻击 (kamacoder.com)
题目描述
在象棋中,马和象的移动规则分别是“马走日”和“象走田”。现给定骑士的起始坐标和目标坐标,要求根据骑士的移动规则,计算从起点到达目标点所需的最短步数。
棋盘大小 1000 x 1000(棋盘的 x 和 y 坐标均在 [1, 1000] 区间内,包含边界)
输入描述
第一行包含一个整数 n,表示测试用例的数量,1 <= n <= 100。
接下来的 n 行,每行包含四个整数 a1, a2, b1, b2,分别表示骑士的起始位置 (a1, a2) 和目标位置 (b1, b2)。
输出描述
输出共 n 行,每行输出一个整数,表示骑士从起点到目标点的最短路径长度。
输入示例
6 5 2 5 4 1 1 2 2 1 1 8 8 1 1 8 7 2 1 3 3 4 6 4 6
输出示例
2 4 6 5 1 0
提示信息
骑士移动规则如图,红色是起始位置,黄色是骑士可以走的地方。
题解:A * 算法(A-Star)
关键在于A*算法实现的部分:
在astar函数中,使用优先队列来存储当前的Knight对象;
循环直到优先队列为空,即所有可能的路径都被检查过;
在每次循环中,从优先队列中取出F值最小的Knight对象,并检查是否到达目标位置;
如果未到达目标位置,则遍历8个可能的方向,计算下一个位置的坐标,并检查是否越界或已经被访问过;
如果下一个位置合法且未被访问过,则更新路径消耗,计算F值,并将其加入优先队列;
当到达目标位置时,循环结束。
实现代码:
void astar(const Knight &k)
{Knight cur, next;que.push(k);while (!que.empty()){cur = que.top();que.pop();if (cur.x == b1 && cur.y == b2)break;for (int i = 0; i < 8; i++) // 遍历骑士的8个可能移动方向{// 得到下一个位置的坐标next.x = cur.x + dir[i][0];next.y = cur.y + dir[i][1];if (next.x < 1 || next.x > 1000 || next.y < 1 || next.y > 1000) // 如果下一个位置越界,则跳过continue;if (!moves[next.x][next.y]) // 如果下一个位置没有被访问过{moves[next.x][next.y] = moves[cur.x][cur.y] + 1; // 更新下一个位置的路径消耗// 开始计算Fnext.g = cur.g + 5; // 统一不开根号,这样可以提高精度,马走日,1 * 1 + 2 * 2 = 5next.h = Heuristic(next); // 计算当前节点到终点的预估消耗next.f = next.g + next.h; // 计算F值que.push(next); // 将下一个位置的Knight对象加入优先队列}}}
}
完整代码实现:
#include <bits/stdc++.h>
using namespace std;int moves[1001][1001]; // 定义一个二维数组moves,用于存储骑士从起点到当前位置的移动步数
int dir[8][2] = {-2, -1, -2, 1, -1, 2, 1, 2, 2, 1, 2, -1, 1, -2, -1, -2}; // 定义一个方向数组dir,用于存储骑士可能的移动方向
int b1, b2;struct Knight // 定义一个结构体Knight,用于存储骑士的当前位置和路径消耗等信息
{int x, y;int g, h, f;bool operator<(const Knight &k) const // 重载运算符,用于优先队列的排序{return k.f < f; // 从小到大排序}
};priority_queue<Knight> que; // 定义一个优先队列que,用于存储Knight对象,并按照f值排序int Heuristic(const Knight &k) // 欧拉距离
{return (k.x - b1) * (k.x - b1) + (k.y - b2) * (k.y - b2); // 统一不开根号,这样可以提高精度
}
// 执行A*算法:参数k是当前的Knight对象
void astar(const Knight &k)
{Knight cur, next;que.push(k);while (!que.empty()){cur = que.top();que.pop();if (cur.x == b1 && cur.y == b2)break;for (int i = 0; i < 8; i++) // 遍历骑士的8个可能移动方向{// 得到下一个位置的坐标next.x = cur.x + dir[i][0];next.y = cur.y + dir[i][1];if (next.x < 1 || next.x > 1000 || next.y < 1 || next.y > 1000) // 如果下一个位置越界,则跳过continue;if (!moves[next.x][next.y]) // 如果下一个位置没有被访问过{moves[next.x][next.y] = moves[cur.x][cur.y] + 1; // 更新下一个位置的路径消耗// 开始计算Fnext.g = cur.g + 5; // 统一不开根号,这样可以提高精度,马走日,1 * 1 + 2 * 2 = 5next.h = Heuristic(next); // 计算当前节点到终点的预估消耗next.f = next.g + next.h; // 计算F值que.push(next); // 将下一个位置的Knight对象加入优先队列}}}
}int main()
{int n, a1, a2;cin >> n;while (n--){cin >> a1 >> a2 >> b1 >> b2;memset(moves, 0, sizeof(moves)); // 每次循环都初始化moves数组为0,确保每个骑士问题都有独立的路径记录// 定义起点Knight对象start// F = G + H// G = 从起点到该节点路径消耗// H = 该节点到终点的预估消耗Knight start;start.x = a1;start.y = a2;start.g = 0;start.h = Heuristic(start);start.f = start.g + start.h;// 执行A*算法,以起点Knight对象start为起点astar(start);// 执行A*算法后,清空优先队列que,以便下一次循环使用while (!que.empty())que.pop();cout << moves[b1][b2] << endl; // 输出本次从起点到目标点的路径消耗,即moves[b1][b2]}return 0;
}
三、小结
这算是图论最后的内容了,难度很大,个人感觉只是理解了大概意思,却难以代码实现,后边二刷的时候会强化理解,继续加油!
相关文章:

【代码随想录训练营第42期 Day61打卡 - 图论Part11 - Floyd 算法与A * 算法
目录 一、Floyd算法与A * 算法 1、Floyd算法 思想 伪代码 2、 A * 算法 思想 伪代码 二、经典题目 题目一:卡码网 97. 小明逛公园 题目链接 题解:Floyd 算法 题目二:卡码网 127. 骑士的攻击 题目链接 题解:A * 算法&a…...

docker和ufw冲突问题
在ubuntu上部署的docker映射的端口,开启防火墙ufw后,在未放通的状态下,还是可以访问 解决办法: 在/etc/docker/daemon.json添加如下配置 {"iptables": false } 然后重启docker服务即可 systemctl daemon-reload s…...

Java(基本数据类型)( ̄︶ ̄)↗
Java 基本数据类型是Java编程语言中用于存储数据值的基本单位。它们直接映射到硬件的处理器上,因此访问速度非常快。Java中的基本数据类型分为四大类:整型、浮点型、字符型、布尔型。每种类型都有其固定的范围和存储大小。 一、整型 1)byte…...

283. 移动0
class Solution(object):def moveZeroes(self, nums):""":type nums: List[int]:rtype: None Do not return anything, modify nums in-place instead."""# 两个指针,left, right,中间夹的都是0,# 像个虫子一样一纵一纵的…...

Mysql删库跑路,如何恢复数据?
问题 删库跑路,数据还能恢复吗? 我们经常听说某某被领导训斥了,对领导心生痛恨,然后登录 Mysql 删库跑路。对于闲聊中经常听说过的一个段子,在现实生活中是否真的发生过,如果发生了,我们该如何解…...

【HarmonyOS】应用引用media中的字符串资源如何拼接字符串
【HarmonyOS】应用引用media中的字符串资源如何拼接字符串 一、问题背景: 鸿蒙应用中使用字符串资源加载,一般文本放置在resoutces-base-element-string.json字符串配置文件中。便于国际化的处理。当然小项目一般直接引用字符串,不需要加载s…...

打开ffmpeg编码器的时候报错:avcodec_open2()返回-22
[h264_v4l2m2m 0x555555617a00] Could not find a valid device [h264_v4l2m2m 0x555555617a00] cant configure encoder 前言:先做一个操作,查找编码器的时候,使用名字查找的方式: const AVCodec *avcodec_find_encoder_by_n…...

R包:ggheatmap热图
加载R包 # devtools::install_github("XiaoLuo-boy/ggheatmap")library(ggheatmap) library(tidyr)数据 set.seed(123) df <- matrix(runif(225,0,10),ncol 15) colnames(df) <- paste("sample",1:15,sep "") rownames(df) <- sapp…...

springboot实战学习(7)(JWT令牌的组成、JWT令牌的使用与验证)
接着上篇博客的学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验的基础上,基本完成用户模块的登录接口的主逻辑以及提到了问题:"用户未登录,需要通过登录,获取到令牌进行登录认证,…...

如何使用numpy反转数组
如何使用numpy反转数组 1、使用np.flip()函数 可以使用flip(m, axisNone)函数来对数组进行反转: m:输入数组 axis:为None则行列都反转 axis:为0则反转行 axis:为1则反转列2、代码 import numpy as np# 创建一维数组 arr np.array([[1, 2, 3, 4, 5],[2, 2, 3, 4…...

Linux·进程概念(上)
1.操作系统 任何计算机系统都包含一个基本的程序合集,称为操作系统(Operator System)。笼统的理解,操作系统包括: 内核(进程管理,内存管理,文件管理,驱动管理) 其他程序(函数库,shell程序) OS的…...

Javax Validation 自定义注解校验(身份证号校验)
一、场景分析 我们使用 SpringMVC 在 Controller 层,对身份证号进行数据校验的话,经常采用以下方式: RestController RequiredArgsConstructor RequestMapping("member") public class MemberController {// 身份证号码正则表达式…...

nid修改orac库和实例名为jyc
由于库太大,并且要求修改源库的实例名,所以考虑采用nid方式重建控制文件,实现名称和路径的完美替换。 oracleJYCDB:/home/oracle/scripts> oracleJYCDB:/home/oracle/scripts>echo $ORACLE_SID orac oracleJYCDB:/home/oracle/scripts…...

无人机之模拟图传篇
无人机的模拟图传技术是一种通过模拟信号传输图像数据的方式,它通常使用无线电模块或专用通信协议进行数据传输。 一、基本原理 模拟图传技术的工作原理是将摄像头或相机设备采集到的图像数据,通过模拟信号的形式进行传输。这些模拟信号在传输过程中可能…...

Ubuntu 20.04安装pycharm2022及配置快捷方式
一、下载与安装 1. 下载 在 官网 下载所需版本,如:下载 2022.3.3 - Linux (tar.gz) 2. 安装 设置自定义安装路径(推荐在 /opt/ 路径下)并安装 mkdir -p ~/Documents/software/pycharm/ cd ~/Documents/software/pycharm/ mv ~/Downloads/pycharm-c…...

uni-app - - - - - 实现锚点定位和滚动监听功能(滚动监听功能暂未添加,待后续更新)
实现锚点定位和滚动监听功能 1. 思路解析2. 代码示例 效果截图示例: 点击左侧menu,右侧列表数据实现锚点定位 1. 思路解析 点击左侧按钮,更新右侧scroll-view对应的scroll-into-view的值,即可实现右侧锚点定位滚动右侧区域&am…...

wordpress迁移到别的服务器
wordpress论坛网站搭建 于2023/11/16写的该文章 一-配置环境 配置LNMP(linuxnginxmysqlphpphpmyadmin)环境或者LAMP(apache) 可以选择集成了这些软件的套件 下载链接:https://www.xp.cn/download.html 手动下载这…...

cefsharp新版本OnBeforeResourceLoad 禁止http自动跳转https显示404错误解决办法 含代码
一、问题 因项目需要,域名没有ssl证书,结果http访问时被强制定向到https前缀,结果会显示404 测试版本cefsharp126.x (x64) 框架 CefSharp.WinForms.NETCore 二、代码(核心代码) 如果请求url是http,且目标是https时,则阻止请求 //判断请求变化 if (url.StartsWith(<…...

RK 方案如何做到上电关机
针对RK方案,公版都是上电开机的,有时候有要求需要上电关机,按键开机,需要把PMU的VDC脚的相关电路去掉即可,只保留一个对地电容。这时候就是上电关机了。RP43/RP47/RP64 电阻都去掉。 沟通交流群QQ:71228861…...

基于量子通讯进行安全认证
8月16日,中国银行的一项发明专利“安全认证方法、装置、电子设备及计算机存储介质”授权公告。其申请于2022年6月29日,公布于2022年9月20日。据悉,该发明中应用了量子通讯/量子随机数相关技术。 事实上,近年来,有多家银行探索研究量子技术。在多家银行的2024半年报中,就…...

C语言贪吃蛇小游戏演示和说明
C语言贪吃蛇小游戏演示和说明 设计贪吃蛇游戏的主要目的是让大家夯实C语言基础,训练编程思维,培养解决问题的思路,领略多姿多彩的C语言。 游戏开始后,会在中间位置出现一条只有三个节点的贪吃蛇,并随机出现一个食物&am…...

C++三大特性——继承性(超万字详解)
目录 前言 一、封装 1. 封装(Encapsulation) 二、继承 1. 构造函数的调用顺序 原理: 2. 析构函数的调用顺序 原理: 3、派生类的隐藏 1. 成员函数隐藏 2. 成员变量隐藏 3. 基类函数的重载隐藏 三、多重继承问题 1. 构…...

electron使用npm install出现下载失败的问题
我在使用electron进行下载时,经常出现一个错误。 HTTPError: Response code 404 (Not Found) for https://registry.npmmirror.com/v21.4.4/electron-v21.4.4-win32-x64.zip 这个时候需要修改一些npm的配置。使用命令npm config list -ls 滑到下面,找到一…...

HT513 2.8W I2S 输入单声道D类音频功率放大器
1 特性 ● 电源供电 PVDD 2.5-6.5V; DVDD/AVDD 3.3V ● 灵活的音频输入: I2S,LJ, RJ TDM 输入 8,16,32,44.1,48,88.2,96,192kHz 采样频率输出功率: 1.40W(PVDD3.6V,RL4Ω,THDN10%) 2.80W(PVDD5.0V,RL4Ω,THDN10%) 4.70W(PVDD6.5V,RL4Ω,THDN10%) ● THDN0.08%(Po1W, …...

[PICO VR]Unity如何往PICO VR眼镜里写持久化数据txt/json文本
前言 最近在用PICO VR做用户实验,需要将用户实验的数据记录到PICO头盔的存储空间里,记录一下整个过程 流程 1.开启写入权限 首先开启写入权限:Unity->Edit->Player->安卓小机器人->Other Settings->Configuration->Wri…...

zico2打靶记录
一、环境搭建 下载地址:https://download.vulnhub.com/zico/zico2.ova 直接双击下载的.ova文件即可在VMware中打开 设置好保存路径后在虚拟机的设置中删除仅主机这个网卡 然后启动靶机 二、信息收集 扫描靶机ip arp-scan -l 扫描一下开放的端口 nmap -p- -sV…...

pick你的第一个人形机器人——青龙强化学习环境测试
文章目录 一、环境配置二、开始训练三、训练成果 最近感受到的大趋势是具身智能,强化学习,模仿学习做人形机器人,这个赛道很火,颇有前些年全力投入做自动驾驶的架势,正好最近用强化学习解决POMDP问题接触到了强化学习&…...

了解主机及进程资源占用情况、性能情况、性能瓶颈,TOP命令输出解释
列表前的字段解释 字段通俗解释top - 03:08:50 up 19:36当前时间是 03:08:50,系统已经运行了 19 小时 36 分钟1 user当前有 1 个用户登录使用系统load average: 0.00, 0.02, 0.00系统在过去 1 分钟、5 分钟和 15 分钟内平均的工作繁忙程度,数值越大表示越忙 对于一个 x个核的…...

计算机网络-小型综合网络的搭建涉及到无线路由交换安全
目录 1 拓扑架构 2 做项目的思路 3 做配置 3.1先做核心交换 3.2 防火墙的配置 4 ac 和ap 的配置 4.1 ac上配置安全的东西 5.1 测试编辑 1 拓扑架构 要求看上面的图 2 做项目的思路 这张网很明显是一个小综合,设计到我们的无线交换,路由…...

CleanClip For Mac 強大的剪貼簿助手Paste替代工具 v2.2.1
软件介绍: CleanClip是一款专为Mac设计的强大剪贴板管理工具,旨在提升用户的工作效率和生产力。这款应用完全采用原生Swift编写,为Mac用户提供了流畅、快速且直观的使用体验。CleanClip不仅支持文本内容的管理,还能处理图片、文件…...