当前位置: 首页 > news >正文

代码随想录算法训练营day76 | Floyd 算法精讲、A * 算法精讲

本次题目来自于卡码网

 ​​97. 小明逛公园 (Floyd 算法精讲)

1、确定dp数组以及下标的含义

grid[i][j][k] = m,表示 节点i 到 节点j 以[1...k] 集合为中间节点的最短距离为m

2、确定递推公式

分两种情况:

  • 节点i 到 节点j 的最短路径经过节点k
  • 节点i 到 节点j 的最短路径不经过节点k

对于第一种情况,grid[i][j][k] = grid[i][k][k - 1] + grid[k][j][k - 1]

第二种情况,grid[i][j][k] = grid[i][j][k - 1]

因为我们是求最短路,对于这两种情况自然是取最小值。

即: grid[i][j][k] = min(grid[i][k][k - 1] + grid[k][j][k - 1], grid[i][j][k - 1])

3、dp数组如何初始化

把k 赋值为 0,本题 节点0 是无意义的,节点是从1 到 n

初始化代码

vector<vector<vector<int>>> grid(n + 1, vector<vector<int>>(n + 1, vector<int>(n + 1, 10005)));  // C++定义了一个三位数组,10005是因为边的最大距离是10^4for(int i = 0; i < m; i++){cin >> p1 >> p2 >> val;grid[p1][p2][0] = val;grid[p2][p1][0] = val; // 注意这里是双向图
} 

grid数组中其他元素数值应该初始化多少呢? 本题求的是最小值,所以输入数据没有涉及到的节点的情况都应该初始为一个最大数。

4、确定遍历顺序

我们来看初始化,我们是把 k =0 的 i 和j 对应的数值都初始化了,这样才能去计算 k = 1 的时候 i 和 j 对应的数值。

这就好比是一个三维坐标,i 和j 是平层,而k 是 垂直向上 的。

遍历的顺序是从底向上 一层一层去遍历。

所以遍历k 的for循环一定是在最外面,这样才能一层一层去遍历

5、举例推导dp数组

if __name__ == '__main__':n, m = map(int, input().split())grid = [[[10005] * (n + 1) for _ in range(n + 1)] for _ in range(n + 1)]  # 因为边的最大距离是10^4for i in range(m):p1, p2, val = map(int, input().split())grid[p1][p2][0] = valgrid[p2][p1][0] = val  # 双向图# 开始 floydfor k in range(1, n + 1):for i in range(1, n + 1):for j in range(n + 1):grid[i][j][k] = min(grid[i][j][k - 1], grid[i][k][k - 1] + grid[k][j][k - 1])# 输出结果z = int(input())for _ in range(z):start, end = map(int, input().split())if grid[start][end][n] == 10005:print(-1)else:print(grid[start][end][n])

空间优化

我们可以做一下 空间上的优化,从滚动数组的角度来看,我们定义一个 grid[n + 1][ n + 1][2] 这么大的数组就可以,因为k 只是依赖于 k-1的状态,并不需要记录k-2,k-3,k-4 等等这些状态。

又由于本层计算中,使用了本层计算过的 grid[i][k] 和 grid[k][j] 是没问题的。那么就没必要区分,grid[i][k] 和 grid[k][j] 是 属于 k - 1 层的呢,还是 k 层的。

if __name__ == '__main__':n, m = map(int, input().split())grid = [[10005] * (n + 1) for _ in range(n + 1)]  # 因为边的最大距离是10^4for i in range(m):p1, p2, val = map(int, input().split())grid[p1][p2] = valgrid[p2][p1] = val  # 双向图# 开始 floydfor k in range(1, n + 1):for i in range(1, n + 1):for j in range(n + 1):grid[i][j] = min(grid[i][j], grid[i][k] + grid[k][j])# 输出结果z = int(input())for _ in range(z):start, end = map(int, input().split())if grid[start][end] == 10005:print(-1)else:print(grid[start][end])

126. 骑士的攻击 (A * 算法精讲)

加入了启发式函数,使用了优先队列,优先队列中自定义了比较函数(https://www.cnblogs.com/xrszff/p/14783972.html)

import heapq# F = G + H
# G = 从起点到该节点路径消耗
# H = 该节点到终点的预估消耗class Knight:def __init__(self):self.x = 0self.y = 0self.g = 0self.h = 0self.f = 0def __lt__(self, other):  # 自定义比较函数return self.f < other.fdef heuristic(k):  # 欧拉距离return (k.x - b1) * (k.x - b1) + (k.y - b2) * (k.y - b2)  # 统一不开根号,这样可以提高精度def astar(k):heapq.heappush(que, k)while que:cur = heapq.heappop(que)if cur.x == b1 and cur.y == b2:breakfor i in range(8):next = Knight()next.x = cur.x + dir[i][0]next.y = cur.y + dir[i][1]if next.x < 1 or next.x > 1000 or next.y < 1 or next.y > 1000:continueif moves[next.x][next.y] == 0: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.hheapq.heappush(que, next)if __name__ == '__main__':dir = [(-2, -1), (-2, 1), (-1, 2), (1, 2), (2, 1), (2, -1), (1, -2), (-1, -2)]que = []heapq.heapify(que)n = int(input())for _ in range(n):a1, a2, b1, b2 = map(int, input().split())moves = [[0] * 1001 for _ in range(1001)]  # 每次重新开辟空间start = Knight()start.x = a1start.y = a2start.g = 0start.h = heuristic(start)start.f = start.g + start.hastar(start)while que:heapq.heappop(que)  # 队列清空print(moves[b1][b2])

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • STM32 - PWR 笔记
  • 【国产开源可视化引擎Meta2d.js】鹰眼地图
  • 算法小练之 位运算基础
  • 百数教学——表单提交校验,为数据准确保驾护航
  • 试用笔记之-汇通Exe可执行文件之pe分析
  • Jenkins构建python项目
  • hf-mirror (huggingface 的国内镜像)
  • 【深度学习基础】环境搭建 Linux报错bash: conda: command not found...
  • [C++]: 模板进阶
  • 【Nvidia+AI相机】涂布视觉检测方案专注提高锂电池质量把控标准
  • 数据分析入门指南:表结构数据(三)
  • MySQL8之mysql-community-devel的作用
  • 基于PHP+MySQL组合开发的家政预约小程序源码系统 带完整的安装代码包以及搭建部署教程
  • android调用openssl库
  • PHP同城多商户多行业系统小程序源码
  • hexo+github搭建个人博客
  • CSS居中完全指南——构建CSS居中决策树
  • Docker 笔记(2):Dockerfile
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • JS实现简单的MVC模式开发小游戏
  • React 快速上手 - 07 前端路由 react-router
  • SpingCloudBus整合RabbitMQ
  • Vue--数据传输
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 入口文件开始,分析Vue源码实现
  • 事件委托的小应用
  • 详解NodeJs流之一
  • python最赚钱的4个方向,你最心动的是哪个?
  • ​你们这样子,耽误我的工作进度怎么办?
  • ‌JavaScript 数据类型转换
  • #单片机(TB6600驱动42步进电机)
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (26)4.7 字符函数和字符串函数
  • (6)设计一个TimeMap
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (剑指Offer)面试题34:丑数
  • (原创)可支持最大高度的NestedScrollView
  • (转) Face-Resources
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .net6使用Sejil可视化日志
  • .NET中的Exception处理(C#)
  • .vimrc 配置项
  • //解决validator验证插件多个name相同只验证第一的问题
  • @Autowired和@Resource的区别
  • @EnableAsync和@Async开始异步任务支持
  • @Tag和@Operation标签失效问题。SpringDoc 2.2.0(OpenApi 3)和Spring Boot 3.1.1集成
  • [202209]mysql8.0 双主集群搭建 亲测可用
  • [23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians
  • [Big Data - Kafka] kafka学习笔记:知识点整理
  • [bzoj2957]楼房重建
  • [C/C++]数据结构 堆的详解
  • [C++]入门基础(1)
  • [Foreman]解决Unable to find internal system admin account