图论·搜索最短路径

例题地址

搜索最短路径

  • 在网格图中按照特定路线搜索,搜索方式基于bfs/dfs
  • 需要搜索出一条源点与终点最短的路径

核心思路

  • 无启发式函数:bfs/dfs+
  • 有启发式函数:dijsktra算法,A*(Astar)…

个人理解

  • 启发式函数:相当于根据点的权重,对搜索的方向有一定判断,不会盲目的搜索,减少了绝大部分的无用功。
  • 启发式函数一般搭配优先级队列(堆)实现

A*算法

  • 有启发式函数的搜索
  • 效率和准确程度很大程度取决于启发式函数

常见启发式函数

  • 欧拉距离:就是平方和,两点距离之差(x1-x2)^2 + (y1-y2) ^2
  • 切比雪夫距离:没用过,有缘再更新
  • 曼哈顿距离:没用过,有缘再更新

核心操作

  • 权值的计算:F=G+H
    • G:源点到当前点走过的距离(不是位移,而是路程),是一个真实值
    • H:利用启发式函数计算得到的距离,是一个期望值
  • 优先级队列:对于权值进行排序,同时实现基于BFS的搜索

个人代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int grid[1009][1009];
int n,a1,a2,b1,b2;
int dir[8][2] = { 2,1,1,2,-1,2,-2,1,-2,-1,-1,-2,1,-2,2,-1 };
struct knight {int x, y, g, h, f;//f=g+h,g起点到当前结点,h当前结点到终点
};
struct cmp {bool operator()(const knight& a, const knight& b) {return a.f > b.f;}
};
priority_queue<knight,vector<knight>,cmp>q;
int getDist(const int &x,const int &y,const int &b1,const int &b2) {return (x - b1) * (x - b1) + (y - b2) * (y - b2);
}
void bfs() {q.push({ a1,a2,0,getDist(0,0,b1,b2),getDist(0,0,b1,b2)});while (!q.empty()) {knight cur = q.top();q.pop();if (cur.x == b1 && cur.y == b2) {cout << grid[cur.x][cur.y] << endl;return;}knight next;for (int k = 0;k<8; k++) {next.x = cur.x + dir[k][0];next.y = cur.y + dir[k][1];if (next.x < 1 || next.x>1000 || next.y < 1 || next.y>1000) {continue;}if (!grid[next.x][next.y]) {grid[next.x][next.y] = grid[cur.x][cur.y] + 1;//更新距离,并且起到标记作用next.g = cur.g + 5;next.h = getDist(next.x, next.y, b1, b2);next.f = next.g + next.h;q.push(next);}       }}
}
void solve(){cin >> n;while (n--) {cin >> a1 >> a2 >> b1 >> b2;memset(grid, 0, sizeof(grid));bfs();while (!q.empty()) {q.pop();}}
}
int main() {std::ios::sync_with_stdio(false);std::cin.tie(0); std::cout.tie(0);solve();return 0;
}

注意事项

  • G是路程,利用next.g=getDist(next.x,next.y,a1,a2);计算与源点的距离是错误的
  • grid数组不建议使用vector数组,因为每次使用完都要memset
  • grid仍然需要标记:这里grid本身就可以起到标记作用
  • 题目的步数可以直接由grid统计得到

A*算法空间优化-IDA

蜀黍不会,有缘更新


dijsktra作为启发式函数

核心操作

  • 结构体:结构体的dist定义为源点与当前点的距离
  • 队列:根据结构体的dist排序
  • dist数组的定义:定义dist数组是为了比较二者距离,判断是否应该更新(个人觉得比较累赘,但是不得不定义)
using namespace std;
using ll = long long;
vector<vector<int>>grid(1009, vector<int>(1009, 0));
int n,a1,a2,b1,b2;
int dir[8][2] = { 2,1,1,2,-1,2,-2,1,-2,-1,-1,-2,1,-2,2,-1 };
struct knight {int x, y, dist;
};
struct cmp {bool operator()(const knight&a,const knight&b) {return a.dist > b.dist;}
};
priority_queue<knight, vector<knight>, cmp>q;
vector<vector<int>>dist(1009, vector<int>(1009, INT_MAX));
void bfs(vector<vector<int>>dist) {dist[a1][a2] = 0;q.push({ a1,a2,dist[a1][a2]});while (!q.empty()) {knight cur=q.top();q.pop();if (cur.x == b1 && cur.y == b2) { cout << dist[cur.x][cur.y]<<endl;return;}knight next;for (int k = 0; k < 8; k++) {//相当于选点操作next.x = cur.x + dir[k][0];next.y = cur.y + dir[k][1];if (next.x < 1 || next.x>1000 ||next.y < 1 || next.y > 1000) {continue;}//因为题目说了一定能找到,所以可以没有visited数组的标记//相当于更新if (cur.dist + 1 < dist[next.x][next.y]) {//注意每走一步+1;dist数组也要更新dist[next.x][next.y] = cur.dist + 1;q.push({ next.x,next.y,dist[next.x][next.y] });}}}
}
void solve(){cin >> n;while (n--) {cin >> a1 >> a2 >> b1 >> b2;bfs(dist);//传入dist数组作为形参while (!q.empty()) {q.pop();}}
}
int main() {std::ios::sync_with_stdio(false);std::cin.tie(0); std::cout.tie(0);solve();return 0;
}

注意事项

  • grid数组因为没有权值(权值为1)所以在dijsktra算法中属于无效部分,只起到存储网格作用
  • dist数组作为形参,不能使用引用

时间复杂度:

  • A*算法时间复杂度明显更优,但难以确定,取决于启发函数。但对比BFS/DFS/dijsktra算法是相当大的提升
  • dijsktra算法在面对无权值(权值为1)的图时,退化为BFS
  • BFS/DFS时间复杂度高

参考于代码随想录

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

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

相关文章

[沫忘录] Redis的配置与使用技巧

[沫忘录] Redis的配置与使用技巧 windows的Redis文件配置 windows下的redis文件配置信息主要集中在"redis.windows.conf"这一文件当中。 配置文件中以下参数可以设置Redis的内存大小和栈空间大小。 maxmemory 字节数 maxheap 字节数redis十大数据类型 key的常见…

打造坚固的SSH防护网:端口敲门入门指南

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 打造坚固的SSH防护网&#xff1a;端口敲门入门指南 前言什么是端口敲门端口敲门的优点1. 增强安全…

中介子方程三十六

XXFXXuXXWXXuXXdXXrXXαXXuXpXXKXηXiXXnXXiXηXKXXpXuXXαXXrXXdXXuXWXπXXWXeXyXeXbXπXpXXNXXqXeXXrXXαXXuXpXXKXηXiXXnXXiXηXKXXpXuXXαXXrXXeXqXXNXXpXπXbXeXyXeXWXXπXWXuXXdXXrXXαXXuXpXXKXηXiXXnXXiXηXKXXpXuXXαXXrXXdXXuXXWXXuXXFXXEXXyXXEXXrXXαXXuXpXXKXη…

Java_Java基础:HashCode详解

Hashcode的作用 java的集合有两类&#xff0c;一类是List&#xff0c;还有一类是Set。前者有序可重复&#xff0c;后者无序不重复。当我们在set中插入的时候怎么判断是否已经存在该元素呢&#xff0c;可以通过equals方法。但是如果元素太多&#xff0c;用这样的方法就会比较满…

【Python】Tkinter图形用户界面

窗口管理 tk.TK()&#xff1a;创建主窗口对象。 参数&#xff1a;无。 返回值&#xff1a;返回一个 Tkinter 主窗口对象。 import tkinter as tk root tk.Tk() # 创建主窗口root.mainloop()&#xff1a;启动 Tkinter 主事件循环&#xff0c;使窗口保持显示并等待用户交互…

网络扫描工具Nmap

一、Nmap简介 Nmap是一款功能强大的网络扫描工具&#xff0c;用于网络发现和安全审计。 Nmap&#xff0c;即网络映射器&#xff08;Network Mapper&#xff09;&#xff0c;是一个广受欢迎的开源工具&#xff0c;主要用于网络的主机发现、端口扫描、服务检测以及操作系统识别…

Java 中常见的数据结构算法及其应用

Java 中常见的数据结构算法及其应用 在Java编程中&#xff0c;选择合适的数据结构对程序的性能和可维护性至关重要。本文将详细介绍Java中常见的数据结构及其应用场景&#xff0c;包括数组、链表、栈、队列、双端队列、集合、映射、堆、树、图和列表。 1. 数组 (Array) 数组…

React的Redux的状态管理

步骤 1.创建新项目 npx create-react-app react-redux 2.安装配套工具 npm i reduxjs/toolkit react-redux 3.启动项目 npm run start 4.在src目录下创建store文件夹 5.在store文件夹下创建modules文件夹 6.在store文件夹里创建index.js文件 7.在counterStore.js文件…

Python入门-基础知识-模块

Python程序中的模块的功能与函数相似&#xff0c;有助于更好地组织代码&#xff0c;提高代码的利用率。模块是一 种以“.py”为扩展名的文件&#xff0c;其中可以包含变量、函数等各种代码形式。导入模块后&#xff0c;就可以使用 模块中的变量、函数等。Python库着重强调功能性…

随着量子计算的崭露头角,C 语言在未来是否需要做出适应性的改变,以适应新的计算架构和算法?

随着量子计算的发展&#xff0c;C语言可能需要进行一些适应性的改变以适应新的计算架构和算法。量子计算与经典计算存在很大的差异&#xff0c;涉及到量子比特、量子门和量子算法等概念。因此&#xff0c;为了更好地支持量子计算&#xff0c;C语言可能需要引入新的数据类型和算…

JS面试题7——localStorage,sessionStorage,cookie的区别

公共点&#xff1a;都是用于在客户端存放数据的 区别&#xff1a; 1. 数据存放的有效期不同 <script> sessionStorage.setItem("key", "123"); // 仅在当前浏览器窗口关闭前有效 localStorage.setItem("key", "456"); // 持久化…

自动化代码规范检查--Sonarqube部署

参考文档 官方文档安装数据库 官方给出几种数据库: # 我们选用postgres, 拉取镜像 docker pull postgres:16.0# 创建存储卷 docker volume create postgresql-data# 运行容器 docker run -d --name sonarqube-postgres \-p 5432:5432 \-e POSTGRES_DB=sonar_DB \-e POSTGRE…

PostgreSQL删除重复数据同时保留每组中的一条记录

PostgreSQL删除重复数据同时保留每组中的一条记录 在 PostgreSQL 中&#xff0c;你不能直接从一个 CTE&#xff08;公共表表达式&#xff09;中删除数据&#xff0c;因为 CTE 只是一个临时的结果集&#xff0c;它并不直接对应一个可以更新的表。但是&#xff0c;你可以使用 CT…

Nsight Compute 是怎么计算Roofline的呢

Nsight Compute 是怎么计算Roofline的呢 1.参考链接2.小结3.Nsight Compute 是怎么计算Roofline的呢4.生成测试程序5.测试规模为8192时的性能6.计算Roofline7.指标解释8.测试规模为1024时的性能9.测试规模为128时的性能10.RTX 3060基础能力测试11.sm__inst_executed.avg.pct_of…

IPv6测试指标有哪些?怎么看网站是否完成IPv6升级改造?

IPv6是互联网第六代协议&#xff0c;以其近乎无限的地址资源为未来互联网的发展提供了广阔空间和无限可能&#xff0c;为物联网、大数据、人工智能等新基建的蓬勃发展提供了坚实的网络支撑。我国高度重视IPv6的发展建设&#xff0c;自2017年《推进互联网协议第六版&#xff08;…

高性价比蓝牙耳机有哪些?2024超高性价比蓝牙耳机推荐

在2024移动互联网高速发展的时代&#xff0c;蓝牙耳机已成为我们生活中不可或缺的一部分。走在街头&#xff0c;低头看手机&#xff0c;滑动屏幕选歌&#xff0c;耳边传来清晰的旋律&#xff0c;这一幕已经成为现代生活的标配。但面对市场上琳琅满目的蓝牙耳机品牌和型号&#…

数据库同步最简单的方法

数据库同步到底有咩有简单的方法&#xff0c;有肯定是有的&#xff0c;就看你有咩有缘&#xff0c;看到这篇文章&#xff0c;你就是有缘人。众所周知&#xff0c;数据库同步向来都不是一件简单的事情&#xff0c;它很繁琐&#xff0c;很费精力&#xff0c;很考验经验&#xff0…

Kali Linux源

中科大 deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib阿里云 deb http://mirrors.aliyun.com/kali kali-rolling main non-free contrib deb-src http://mirrors.…

risc-v 怎么使用内存呢?

内存地址对齐 一般写法 #define ALIGN_4_BYTES 4 #define ALIGN_4_MASK (ALIGN_4_BYTES - 1) //4字节地址对齐 static inline uintptr_t align_4_bytes(uintptr_t address) {return (address ALIGN_4_MASK) & ~ALIGN_4_MASK; }//定义页大小是4k&#xff0c;2的12次方是409…

【LeetCode】每日一题:K个一组反转链表

解题思路 其实更像一个模拟题&#xff0c;但是有两个地方的边界一直没有处理好导致卡了很久。 AC代码 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solut…