97. 小明逛公园,Floyd 算法,127. 骑士的攻击,A * 算法

97. 小明逛公园

Floyd 算法

dijkstra, bellman_ford 是求单个起点到单个终点的最短路径,dijkstra无法解决负权边的问题, bellman_ford解决了负权边的问题,但二者都是基于单起点和单终点。

而Floyd 算法旨在解决多个起点到多个终点的最短路径问题,且Floyd 算法对边的权值正负没有要求,都可以处理Floyd 算法采用的是动态规划的思想,那涉及到动态规划就需要用到动态规划五部曲了。

  • 1. dp定义

dp[i][j][k] 表示 节点i 到 节点j 以[1...k] 集合中的一个节点为中间节点的最短距离

k 是指取 区间[1,k] 中的一个节点作为中间节点;节点i 到 节点j 的最短路径中 一定是经过很多节点,那么这个集合用[1...k] 来表示。

  • 2. dp初始化

刚开始进来时,每条边的关系进来时都不需要经过中间节点,因此输入的边的关系用dp[i][j][0]进行初始化。

  • 3. dp递推公式

当到达节点k时,此时有两种状态,一种是经过节点k,另外一种是不经过中间节点k。

  1. 经过节点k,那此时dp[i][j][k] = dp[i][k][k-1] + dp[k][j][k-1]
  2. 不经过中间节点k,那此时dp[i][j][k] = dp[i][j][k-1]

求的是最小距离,因此dp[i][j][k] = min( dp[i][j][k-1] + dp[k][j][k-1], dp[i][j][k-1])

补充:节点1 到 节点9 的最短距离 是不是可以由 节点1 到节点5的最短距离 + 节点5到节点9的最短距离组成呢?即 grid[1][9] = grid[1][5] + grid[5][9]。

  • 4. 遍历顺序

由于初始化得到的是一个平面,且递推公式是往上去进行递推的,因此需要三个循环去进行递推,k处于外循环,i,j构成内循环。即先平面再高度的方式去进行递推。

  • 5. 打印dp

Code:


if __name__ == "__main__":scenery_size, road_size = map(int, input().split())length = scenery_size + 1# 1. dp数组定义dp = [ [[float('inf')]*length for _ in range(length)] for _ in range(length) ]     ##先构造一个二维数组,再外封遍历从而构成三维数组# 2. dp初始化for _ in range(road_size):u, v, w = map(int, input().split())dp[u][v][0] = w         dp[v][u][0] = w         ## 无向图Q = int(input())plan = []for _ in range(Q):start, end = map(int, input().split())plan.append([start,end])# 3. 递推公式# dp[i][j][k] = min(dp[i][j][k-1], dp[i][k][k-1]+dp[k][j][k-1])# 4.遍历顺序for k in range(1, length):for i in range(1,length):for j in range(1,length):dp[i][j][k] = min(dp[i][j][k-1], dp[i][k][k-1]+dp[k][j][k-1])# 5. 打印dp数组for i in range(len(plan)):  ## 结果输出start = plan[i][0]end = plan[i][1]if dp[start][end][scenery_size] != float('inf'):print(dp[start][end][scenery_size])else:print(-1)

其他:

  • dp = [ [[float('inf')]*length for _ in range(length)] for _ in range(length) ]

先构造 length 个list, 然后每个list里面存储的是一个二维矩阵。

  • Floyd的算法是基于点的角度去进行计算的,因此适合于稠密图(边多),不适合稀疏图(边少)。也就说当你图中有1万个点,但只有一条边时,此时用这个算法就不合适。(计算时间复杂度O(n^3), n是节点数目)

127. 骑士的攻击

A * 算法

关键:启发式函数,来确定广搜的方向。

A * 算法其实就是个改进版的广搜,其与BFS的区别如下。BFS是每次都往四面八方去进行搜索,而A*会计算当前离终点的距离去判断要往那个方向进行广搜,从而极大减少了广搜的次数。

由于每次BFS都是选取dis最小的一个元素进行下一次BFS,因此需要用到小顶堆

dis = cur_dis + remaining_dis(通过引入这个变量来明确遍历的方向)

  • cur_dis: 表示从起点出发到当前节点时已走过的步数。(题目要求是输出步数,而不是距离)
  • remaining_dis:当前节点 到 终点的距离。
  • dis 与 cur_dis  呈正相关,当dis有最小时,此时cur_dis有最小。

如何计算、保存 cur_dis,并通过小顶堆对dis进行排序,通过堆顶元素来指导BFS的方向是这道题的关键。  

Code

from collections import deque
import heapq
import mathdirections = [[2,1],[-2,1],[1,2],[-1,2],[2,-1],[-2,-1],[1,-2],[-1,-2]]def caculate_dis(point_1, point_2):     ## 计算当前点到终点的距离return ((point_1[0] - point_2[0]) ** 2 + (point_1[1] - point_2[1]) ** 2) ** 0.5    ### **2 表示平方, ** 0.5 表示sqrt(),即开根def A_star(start, end):dis = -1length = 1001q = [ (caculate_dis(start, end), start) ]   ## 队列内存储一个元组,元组包含了距离信息和起点位置。在小顶堆中会优先对元组中靠左的元素进行排序heapq.heappush(q, (caculate_dis(start, end), start))step = {start: 0}       ## 一个字典,来记录从起点到当前节点所走过的距离。数组不能作为key值while q:        ## q是一个队列,跟BFS的思路一样dis, cur = heapq.heappop(q)     ## 推出小顶堆的堆顶if cur == end:      ## 当前节点抵达终点return step[cur]for x_move, y_move in directions:new_x = cur[0] + x_movenew_y = cur[1] + y_moveif new_x < 1 or new_x > 1000 or new_y < 1 or new_y > 1000:continuenew = (new_x, new_y)step_new = step[cur] + 1  #计算起点到当前节点所走过的距离,每走一次加一次if step_new < step.get(new, float('inf')):  ## 不存在new这个key时,输出inf。 如果从起点出发有走更少的距离抵达目前这个点,则不更新step[new] = step_new  # 记录从起点到当前节点所走过的距离heapq.heappush(q, (caculate_dis(new, end)+step[new], new))if __name__ == "__main__":test_num = int(input())for _ in range(test_num):start_x, start_y, end_x, end_y = map(int, input().split())start = (start_x, start_y)end = (end_x, end_y)min_List = A_star(start, end)print(min_List)
from collections import defaultdict
import math
import heapqdirections = [ [2,1], [2,-1],[1,2], [1, -2],[-2,1], [-2,-1],[-1,2], [-1,-2],]def caculate_dis(cur, end):         ## 这里不能改精度,会影响搜索dis = math.sqrt((cur[0] - end[0])**2 + (cur[1] - end[1])**2)return disdef A_star(start, end):queue = [(caculate_dis(start,end), start)]heapq.heappush(queue, (caculate_dis(start,end), start))step = {}step[start] = 0while queue:dis, cur = heapq.heappop(queue)if cur == end:return disfor x_move, y_move in directions:new_x = cur[0] + x_movenew_y = cur[1] + y_moveif new_x < 1 or new_x > 1000 or new_y < 1 or new_y > 1000:continuenew = (new_x, new_y)step_new = step[cur] + 1if step_new < step.get(new, float('inf')):step[new] = step_newheapq.heappush(queue, ((caculate_dis(new, end)+step_new),new))## 浮点数+整数 = 浮点数,后续堆result结果进行int转换就行if __name__ == "__main__":test_num = int(input())for _ in range(test_num):start_x, start_y, end_x, end_y = map(int, input().split())start = (start_x, start_y)end = (end_x, end_y)min_result = A_star(start, end)print(int(min_result))

注意:

  • 为什么需要这个判断 if step_new < step.get(new, float('inf'))

因为走到同一个节点下所用的步数可以步数,但我么要求的是所用步数最少的。如上,只有红色箭头是所花步数是最少的。

  • 另外由于A*算法具有一定的方向性(小顶堆+dis实现),因此每次BFS只会选取一个更靠近终点的点进行下一次BFS,故不会存在因为重复遍历而出现死循环的问题。

缺点:

  • 小顶堆内维护了很多元组,但实际用到的时候只是使用到了堆顶。如果在一次路径搜索中,大量不需要访问的节点都在队列里,会造成空间的过度消耗。
  • A*算法只擅长给出明确的目标 然后找到最短路径。如果给出 多个可能的目标,然后在这多个目标中 选择最近的目标,则A * 就不擅长了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/96568.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/96568.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

​崩坏世界观中的安全漏洞与哲学映射:从渗透测试视角解构虚拟秩序的脆弱性​

​崩坏世界观&#xff1a;游戏中的世界&#xff0c;是真实&#xff0c;也是虚幻的&#xff01;对于游戏中的NPC角色而言&#xff0c;TA们生存的世界&#xff0c;是真实的&#xff01;对于游戏玩家而言&#xff0c;游戏中的世界&#xff0c;是虚拟的&#xff01;通过沉浸式的游戏…

【离线安装】CentOS Linux 7 上离线部署Oracle 19c(已成功安装2次)

1.部署参考链接&#xff1a; CentOS 7 rpm方式离线安装 Oracle 19chttps://blog.csdn.net/Vampire_1122/article/details/123038137?fromshareblogdetail&sharetypeblogdetail&sharerId123038137&sharereferPC&sharesourceweixin_45806267&sharefromfrom…

小白向:Obsidian(Markdown语法学习)快速入门完全指南:从零开始构建你的第二大脑(免费好用的笔记软件的知识管理系统)、黑曜石笔记

一、认识Obsidian&#xff1a;不只是笔记软件的知识管理系统 1.1 什么是Obsidian Obsidian是一个基于本地存储的知识管理系统&#xff0c;它将你的所有笔记以纯文本Markdown格式保存在电脑本地。这个名字来源于黑曜石——一种火山熔岩快速冷却形成的玻璃质岩石&#xff0c;象…

攻防世界—Confusion1—(模板注入ssti)

一.解题在login和register的页面中发现这个文件路径接下去就找有什么点可以利用二.ssti通过题目信息可知是一只蛇把一只大象缠绕起来了&#xff0c;蛇代表python&#xff0c;大象代表php这边通过python可以推测可能是模板注入&#xff0c;这边我看其他的解题是说通过看报文信息…

【Protues仿真】基于AT89C52单片机的超声波测距

目录 1 HCSR04超声波测距传感器 1.1 基本参数 1.2 引脚说明 1.3 工作原理&#xff08;时序图&#xff09; 2 基于AT89C52单片机的超声波测距电路原理图 2.1 硬件连接说明 2.2 工作原理 3 基于AT89C52单片机的超声波测距控制程序 3.1.1 初始化设置 3.1.2 超声波测距原…

LLM - Agent核心架构:四大“身体”部件

文章目录一、Agent核心架构&#xff1a;四大“身体”部件1. 核心大脑&#xff1a;大型语言模型&#xff08;LLM&#xff09;2. 记忆系统&#xff1a;短期与长期记忆3. 工具箱&#xff08;Toolkit&#xff09;&#xff1a;从“思想家”到“行动家”4. 驱动循环&#xff08;Engin…

html-docx-js 导出word

2025.08.23今天我学习了如何将html页面内容导出到word中&#xff0c;并保持原有格式&#xff0c;效果如下&#xff1a;代码如下&#xff1a;1&#xff1a;列表页面按钮<el-button type"warning" plain icon"el-icon-download" size"mini" cli…

Science Robotics 通过人机交互强化学习进行精确而灵巧的机器人操作

机器人操作仍然是机器人技术中最困难的挑战之一&#xff0c;其方法范围从基于经典模型的控制到现代模仿学习。尽管这些方法已经取得了实质性进展&#xff0c;但它们通常需要大量的手动设计&#xff0c;在性能方面存在困难&#xff0c;并且需要大规模数据收集。这些限制阻碍了它…

Dism++备份系统时报错[句柄无效]的解决方法

当使用Dism进行系统备份时遇到“[句柄无效]”的错误&#xff0c;这通常是由于某些文件或目录的句柄无法正确访问或已被占用所导致。以下是一种有效的解决方法&#xff1a;一、查看日志文件定位日志文件&#xff1a;首先&#xff0c;打开Dism软件所在的目录&#xff0c;并找到其…

华为/思科/H3C/锐捷操作系统操作指南

好的,这是一份针对 华为(VRP)、思科(IOS/IOS-XE)、H3C(Comware)和锐捷(Ruijie OS) 这四大主流网络设备厂商操作系统的对比操作指南。本指南将聚焦于它们的共性和特性,帮助你快速掌握多厂商设备的基本操作。 四大网络厂商操作系统综合操作指南 一、 核心概念与模式对…

一文读懂 DNS:从域名解析到百度访问全流程

目录 前言 一、什么是 DNS&#xff1f;—— 互联网的 “地址簿” 为什么需要 DNS&#xff1f; DNS 的核心参数 二、DNS 解析原理&#xff1a;递归与迭代的协作 1. 两种核心查询方式 2. 完整解析流程&#xff08;以www.baidu.com为例&#xff09; 缓存清理命令 三、DNS …

初试Docker Desktop工具

文章目录1. 概述2. 下载3. 安装4. 注册5. 登录6. 启动7. 容器8. 运行容器8.1 运行容器的镜像8.2 获取示例应用8.3 验证Dockerfile文件8.4 拉取Alpine精简镜像8.5 创建镜像8.6 运行容器8.7 查看前端9. 访问静态资源9.1 本地静态资源9.2 创建服务器脚本9.3 修改Dockerfile文件9.4…

百度披露Q2财报:营收327亿,AI新业务收入首超百亿

8月20日&#xff0c;百度发布2025年第二季度财报&#xff0c;显示季度总营收327亿元&#xff0c;百度核心营收263亿元&#xff0c;归属百度核心净利润74亿元&#xff0c;同比增长35%。受AI驱动&#xff0c;涵盖智能云在内的AI新业务收入增长强劲&#xff0c;首次超过100亿元&am…

【字母异位分组】

思路 核心思路&#xff1a;使用排序后的字符串作为键&#xff0c;将原始字符串分组 键的选择&#xff1a;对于每个字符串&#xff0c;将其排序后得到标准形式作为键分组存储&#xff1a;使用哈希表&#xff0c;键是排序后的字符串&#xff0c;值是对应的原始字符串列表结果构建…

高防cdn如何缓存网页静态资源

为什么需要优化网页静态资源的缓存&#xff1f; 网页静态资源包括图片、CSS、JavaScript等文件&#xff0c;它们通常体积大、访问频繁。在网页访问过程中&#xff0c;如果每次都从源服务器请求这些静态资源&#xff0c;会导致网络延迟和带宽消耗。而优化网页静态资源的缓存&am…

使用Pandas进行缺失值处理和异常值检测——实战指南

目录 一、缺失值处理 1.1 缺失值的识别 1.2 删除缺失值 1.3 填充缺失值 二、异常值检测 2.1 异常值的定义 2.2 常用检测方法 IQR&#xff08;四分位数间距&#xff09;法 Z-score&#xff08;标准分数&#xff09;法 三、实战案例&#xff1a;基因表达数据预处理 四…

B.30.01.1-Java并发编程及电商场景应用

摘要 本文深入探讨了Java并发编程的核心概念及其在电商系统中的实际应用。从基础并发机制到高级并发工具&#xff0c;结合电商业务场景中的典型问题&#xff0c;如高并发秒杀、库存管理、订单处理等&#xff0c;提供了实用的解决方案和最佳实践。 1. Java并发编程基础 1.1 并发…

怎样避免游戏检测到云手机?

以下是一些可能避免游戏检测到云手机的方法&#xff1a;云手机可能会因网络配置等因素出现一些异常网络行为&#xff0c;如网络延迟的规律性变化等&#xff0c;在使用云手机玩游戏时&#xff0c;尽量保持网络行为的稳定性和自然性&#xff0c;避免短时间内频繁切换网络连接&…

文件上传 --- uploadlabs靶场

目录 1 前端和js校验 抓包改包 2 . 2.1 .htaccess&#xff08;伪静态&#xff09; 2.2 %00截断 &#xff08;php5.2&#xff09; 2.3 user_init_ 2.4 3 图片码防御 4 竞争型漏洞 思路&#xff1a; 容易出现的问题: 1 前端和js校验 关闭JS的代码&#xff0c;上传PHP…

汉化版本 k6 dashboard

目前官方提供的 dashboard 只有英文版本&#xff0c;国内使用不方便&#xff0c;因此 fork 了下官方仓库&#xff0c;添加了汉化版本 https://github.com/kinghard7/xk6-dashboardhttps://github.com/kinghard7/xk6-dashboard安装 xk6 构建程序&#xff1a;go install go.k6.i…