【算法】复习搜索与图论

🍎 博客主页:🌙@披星戴月的贾维斯
🍎 欢迎关注:👍点赞🍃收藏🔥留言
🍇系列专栏:🌙 蓝桥杯
🌙请不要相信胜利就像山坡上的蒲公英一样唾手可得,但是请相信,世界上总有一些美好值得我们全力以赴,哪怕粉身碎骨!🌙
🍉一起加油,去追寻、去成为更好的自己!

文章目录

  • 前言
  • 🍎1.中国象棋中的马的行动
      • 题目描述
      • 输入格式
      • 输出格式
  • 🍎2.Dijkstra求最短路 I(图论)
      • 题目描述
  • 🍎3.Dijkstra求最短路 II
  • 🍎4. spfa求最短路
  • 🍎总结

提示:以下是本篇文章正文内容,下面案例可供参考


前言

    深度遍历算法(depth first search)俗称dfs和 广度优先遍历(broad first search)俗称bfs以及我们常听到的图论里面的最短路问题,借着这篇文章我们一起深入了解一下这些算法的逻辑和解法。

🍎1.中国象棋中的马的行动

题目描述

在中国象棋中,马的行动方式是“日”字形。假设我们有一个 8x8 的棋盘,棋盘的左上角是(0,0),右下角是(7,7)。马开始时位于给定的位置(x,y),你的任务是计算马需要多少步才能到达目标位置(a,b)。如果马不能到达目标位置,就返回-1。

注意:马只能按照“日”字形行动,即先向上或向下移动两步,然后向左或向右移动一步,或者先向左或向右移动两步,然后向上或向下移动一步。

输入格式

输入共两行,每行包含两个整数。第一行是马的初始位置(x,y),第二行是马的目标位置(a,b)。所有的整数都在0到7之间。

输出格式

输出一个整数,表示马到达目标位置需要的最少步数。如果不能到达,就输出-1。
输入输出样例
0 0;
7 7;

输出样例:
6

老规矩, 我们要养成一个好的写程序习惯,那就是先写思路,再写实现过程

解题思路:
    首先,我们可以通过看数据范围大致判断这一题用到的算法,数据范围才8,可以支持dfs,bfs,dp等等各种算法,而且我们读题可以知道,🐎的行动方式是“日”字形,即可以画图得出它的方向图
在这里插入图片描述
即我们可以设置一个距离数组,通过bfs去枚举这八个方向,算出初始点到各个可能到达点的距离,我们通过队列来存储可能到达的下一个点,如果队列里面没有数字了就代表遍历结束,返回值。

代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
#define x first
#define y second
bool st[10][10];
int d[10][10];
int a1, b1, a2, b2;
int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2}, dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
int bfs(int x, int y)
{queue<pii> q;q.push({x, y});//把点放入队列st[x][y] = true;//标记while(q.size()){auto t = q.front();q.pop();if(t.x == a2 && t.y == b2) return d[a2][b2];//如果找到直接返回距离数组for(int i = 0; i < 8; i++){int ax = t.x + dx[i], ay = t.y + dy[i];if(ax < 0 || ax > 7  || ay < 0 || ay > 7 || st[ax][ay] == true) continue;st[ax][ay] = true;d[ax][ay]=d[t.x][t.y]+1;q.push({ax, ay});}}return -1;//如果找不到就返回-1
}
int main ()
{cin >> a1 >> b1;cin >> a2 >> b2;int t = bfs(a1, b1);cout << t << endl; return 0;
}

写法2:dfs深度搜索

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
#define x first
#define y second
bool st[10][10];
int dist[10][10];
int a1, b1, a2, b2;
int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2}, dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
void dfs(int x, int y)
{if(x == a2 && y == b2) return;//判断结束条件for(int i = 0; i <= 7; i++){int tx = x + dx[i];int ty = y + dy[i];if(tx < 0 || tx > 7 || ty < 0 || ty > 7)continue;if(dist[tx][ty] > dist[x][y] + 1){dist[tx][ty] = dist[x][y] + 1;dfs(tx, ty);}}return;
}
int main ()
{cin >> a1 >> b1;cin >> a2 >> b2;memset(dist, 0x3f, sizeof dist); //先将方向数组置为0x3fdist[a1][b1] = 0;dfs(a1, b1);if(dist[a2][b2] == 0x3f3f3f3f) cout << "-1" << endl;//如果没有搜到就输出-1else cout << dist[a2][b2] << endl;//否则输出距离return 0;
}

学习搜索我还推荐大家去看走迷宫和红与黑这两题,都是比较经典的。

🍎2.Dijkstra求最短路 I(图论)

题目描述

由于题目复制会乱码,所以博主干脆用图片代替。
在这里插入图片描述
图论问题和dp问题的区别

dp是选择下一个数(选择下一个状态)

图论是选择这个小的点去更新后继的节点
在这里插入图片描述
如下图例子:
在这里插入图片描述
在这个例子中,我们把已经确定的最短的距离标为绿色,这时候我们t = 2这个节点,发现3这个节点 的距离到原点是4大于2 + 1,更新3和节点1的最短距离。
代码示例:

dist数组存储的是第一个节点到第 j个节点的距离是累加的

#include<bits/stdc++.h>
using namespace std;
//存稠密图用邻接矩阵
const int N = 510;
int n, m;
int g[N][N];
int dist[N];
bool st[N];int dijkstar()
{memset(dist, 0x3f, sizeof dist); // 1、先初始化距离dist[1] = 0; //1号点到自己的距离为0for(int i = 0; i < n; i++){int t = -1;for(int j = 1; j <= n; j++) //遍历所有点{if(!st[j] && (t == -1 || dist[t] > dist[j]))//如果j没有遍历过和t == -1或者t这点的距离>j的距离,更新tt = j;}st[t] = true;for(int j = 1; j <= n; j++){dist[j] = min(dist[j], dist[t] + g[t][j]);//g的ab是a 到b 点的距离}}if(dist[n] == 0x3f3f3f3f) return -1;else return dist[n];}
int main ()
{ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m; //n个点m条边memset(g, 0x3f, sizeof g);while(m --){int a, b, c;cin >> a >> b >> c;g[a][b] = min(g[a][b], c);}int h = dijkstar();cout << h << endl;return 0;
}

🍎3.Dijkstra求最短路 II

在这里插入图片描述

思路:n的数据范围从500 到了 1.5 * 10的五次方,数据量一下子变得很大,用邻接矩阵去存储很容易爆内存,而且会超时,所以要用邻接表去存。而且为了提高效率,我们要用优先级队列。
时间复杂度m*logn


#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define x first
#define y secondtypedef pair<int, int> pii;
int h[N], ne[N], e[N], idx, w[N];
int n, m;
bool st[N];
int dist[N];
void add(int a, int b, int c)
{e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] =idx++;
}
int dijkstart()
{memset(dist, 0x3f, sizeof dist);dist[1] = 0;priority_queue<pii, vector<pii>, greater<pii>> q;q.push({0, 1}); //1号点,距离是0,编号是1while(q.size()){auto t = q.top();q.pop();int ver = t.y, d = t.x; if(st[ver]) continue; //说明遍历过了st[ver] = true; //标记for(int i = h[ver]; i!= -1; i = ne[i]){int j = e[i];//当前节点if(dist[j] > d + w[i]){dist[j] = d + w[i];q.push({dist[j], j});}}}if(dist[n] == 0x3f3f3f3f) return -1;else return dist[n];
}
int main ()
{memset(h, -1, sizeof h);cin >> n >> m;while(m --){int a, b, c;cin >> a >> b >> c;add(a, b, c);}int h = dijkstart();cout << h << endl;return 0;
}

🍎4. spfa求最短路

在这里插入图片描述
如果说边的距离全部都是正的,我们用dijkstart算法,那么如果存在负边权,那么我们可以采用spfa算法,而且spfa算法效率会高很多,时间复杂度是0(n * m)。同样,我们可以用spfa算法解决之前dijkstart算法的题,spfa的写法很像上一道题,利用邻接表去存储,然后利用队列把距离短的点存储起来,然后去更新后继节点。但是我可能会比较嫌弃邻接表写法比较复杂,我们可以用vector<结构体>这样的形式来存储图。
代码示例:

#include<bits/stdc++.h>
using namespace std;typedef pair<int, int> PII;
const int N = 1e5 + 10;
int n, m;
struct Node
{int node;int w;
};
int dist[N];
bool st[N];vector<Node> g[N];//二维的数组
int spfa()
{memset(dist, 0x3f, sizeof dist);dist[1] = 0;queue<int> q; //队列存储所有待更新的点q.push(1); //把1号点放入队列st[1] = true;// st数组存当前这个点是否在队列当中while(q.size()){int t = q.front();//每次取出队头q.pop();st[t] = false;//更新所有领边for(int i = 0; i < g[t].size(); i ++){int j = g[t][i].node;if(dist[j] > dist[t] + g[t][i].w){dist[j] = dist[t] +  g[t][i].w;if(!st[j]){q.push(j);st[j] = true;}}}}return dist[n];
}
int main ()
{cin >> n >> m;while(m --){int a, b, c;cin >> a >> b >> c;g[a].push_back({b, c});}int t = spfa();if(t == 0x3f3f3f3f) cout << "impossible";else cout << t << endl;return 0;
}

🍎总结

    本文和大家介绍了几题搜索和图论的题目,既帮助了自己复习,也希望对读者有所帮助!

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

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

相关文章

C++二分查找算法:规划兼职工作

题目 你打算利用空闲时间来做兼职工作赚些零花钱。 这里有 n 份兼职工作&#xff0c;每份工作预计从 startTime[i] 开始到 endTime[i] 结束&#xff0c;报酬为 profit[i]。 给你一份兼职工作表&#xff0c;包含开始时间 startTime&#xff0c;结束时间 endTime 和预计报酬 pro…

Java集合List报错,java.lang.UnsupportedOperationException

目录 一、点击Arrays.asList源码&#xff0c;一探究竟二、习惯了Arrays.asList&#xff0c;就是想用.add()添加元素&#xff0c;怎么办&#xff1f;三、又有一个同事&#xff0c;是这样写的四、重新点击Arrays.asList源码&#xff0c;一探究竟五、全是坑&#xff0c;怎么办&…

Nginx反向代理与负载均衡与504错误

Nginx反向代理与负载均衡概念简介 关于代理 什么是代理 类似中介 在没有代理模式的情况下&#xff0c;客户端和Nginx服务端&#xff0c;都是客户端直接请求服务端&#xff0c;服务端直接响应客户端。 那么在互联网请求里面&#xff0c;客户端往往无法直接向服务端发起请求…

“技能兴鲁”职业技能大赛-网络安全赛项-学生组初赛 WP

Crypto BabyRSA 共模攻击 题目附件&#xff1a; from gmpy2 import * from Crypto.Util.number import *flag flag{I\m not gonna tell you the FLAG} # 这个肯定不是FLAG了&#xff0c;不要交这个咯p getPrime(2048) q getPrime(2048) m1 bytes_to_long(bytes(flag.e…

Unity中Shader矩阵的乘法

文章目录 前言一、矩阵乘以标量二、矩阵和矩阵相乘1、第一个矩阵的列数必须 与 第二个矩阵的行数相等&#xff0c;否则无法相乘&#xff01;2、相乘的结果矩阵&#xff0c;行数由第一个矩阵的行数决定&#xff0c;列数由第二个矩阵的列数决定&#xff01; 三、单位矩阵四、矩阵…

VIVADO+FPGA调试记录

vivadoFPGA调试记录 vitis编译vivado导出的硬件平台&#xff0c;提示xxxx.h file cant findVITIS内定义的头文件找不到 vitis编译vivado导出的硬件平台&#xff0c;提示’xxxx.h file cant find’ 此硬件平台中&#xff0c;包含有AXI接口类型的ip。在vitis编译硬件平台时&…

IntelliJ IDE 插件开发 |(一)快速入门

前言 IntelliJ IDEA 作为 Java 开发的首选 IDE&#xff0c;其强大、方便之处不必多说。不过&#xff0c;由于个人或者团队的个性化需求&#xff0c;我们或多或少会想对其功能进行拓展&#xff0c;这时就需要开发插件&#xff08;在 IntelliJ 平台下的所有 IDE 均可运行&#x…

JS-项目实战-更新水果单价更新小计更新总计

1、fruit.js //当页面加载完成后执行后面的匿名函数 window.onload function () {//get:获取 Element:元素 By:通过...方式//getElementById()根据id值获取某元素let fruitTbl document.getElementById("fruit_tbl");//table.rows:获取这个表格的所有的行&a…

计算机毕业设计选题推荐-幼儿园管理微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

Linux(多用户下)查看cuda、cudnn版本、查看已经安装的cuda版本相关命令

查看已经安装的CUDA多个版本 linux 中cuda默认安装在/usr/local目录中&#xff1a; -可以使用命令&#xff1a; ls -l /usr/local | grep cuda查看该目录下有哪些cuda版本&#xff1a; 如果输出&#xff1a; lrwxrwxrwx 1 root root 21 Dec 17 2021 cuda -> /usr/loc…

小型企业网络搭建方案

在这个日益数字化和连接的世界里&#xff0c;一个稳固的小型企业网络是实现高效运作的关键支柱。不论您是在经营一家初创公司还是小型企业&#xff0c;一个可靠的企业网络都是保证顺畅沟通、数据分享以及访问在线资源的重要因素。本篇文章将会引导您完成构建一个小型企业网络的…

Python开源项目GPEN——人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色的实践

无论是自己、家人或是朋友、客户的照片&#xff0c;免不了有些是黑白的、被污损的、模糊的&#xff0c;总想着修复一下。作为一个程序员 或者 程序员的家属&#xff0c;当然都有责任满足他们的需求、实现他们的想法。除了这个&#xff0c;学习了本文的成果&#xff0c;或许你还…

web缓存-----squid代理服务

squid相关知识 1 squid的概念 Squid服务器缓存频繁要求网页、媒体文件和其它加速回答时间并减少带宽堵塞的内容。 Squid代理服务器&#xff08;Squid proxy server&#xff09;一般和原始文件一起安装在单独服务器而不是网络服务器上。Squid通过追踪网络中的对象运用起作用。…

微服务测试怎么做

开发团队越来越多地选择微服务架构而不是单体结构&#xff0c;以提高应用程序的敏捷性、可扩展性和可维护性。随着决定切换到模块化软件架构——其中每个服务都是一个独立的单元&#xff0c;具有自己的逻辑和数据库&#xff0c;通过 API 与其他单元通信——需要新的测试策略和新…

RT-Thread STM32F407 定时器

定时器简介 硬件定时器一般有 2 种工作模式&#xff0c;定时器模式和计数器模式。不管是工作在哪一种模式&#xff0c;实质都是通过内部计数器模块对脉冲信号进行计数。下面是定时器的一些重要概念。 计数器模式&#xff1a;对外部输入引脚的外部脉冲信号计数。 定时器模式&…

LayoutLMv3 : 基于统一文本和带Masking图像的文档AI预训练【论文翻译】

文章目录 专业名词统计文档智能多模态预训练模型LayoutLMv3&#xff1a;兼具通用性与优越性LayoutLMv3 &#xff1a; 基于统一文本和带Masking图像的文档AI预训练ABSTRACT1 INTRODUCTION2 LAYOUTLMV32.1 Model Architecture&#xff08;模型架构&#xff09;2.2 Pre-training O…

【JUC】九、线程池ThreadPool

文章目录 1、线程池2、分类3、线程池的使用4、工作流程5、拒绝策略6、线程池的七个参数7、自定义线程池8、什么时候考虑使用线程池&#xff1f; 1、线程池 线程池和数据库连接池的理念很相似&#xff0c;对于数据库连接池&#xff1a;普通的连接数据库是建立一个JDBC连接&…

Linux_系统信息_uname查看内核版本、内核建立时间、处理器类型、顺便得到操作系统位数等

1、uname --help 使用uname --help查看uname命令的帮助信息 2、uname -a 通过上面的help就知道-a选项显示全部内容时的含义了。 内核名是Linux主机名是lubancat&#xff0c;如果想看主机名可以使用命令hostname&#xff1b;内核版本是Linux 4.19.232&#xff0c;建立时间为2…

C语言之深入指针及qsort函数(五)(详解介绍)

C语言之深入指针 在这篇博客看不懂的可以看看这篇C语言之深入指针&#xff08;四&#xff09;在上篇博客中介绍了&#xff1a; 函数指针变量函数指针数组简易计算器的实现\ 文章目录 C语言之深入指针1 回调函数2 qsort函数的使用2.1 使用冒泡排序排序整型数组2.2 使用qsort函数…

什么是脏读、不可重复读、幻读讲解

数据库隔离级别是数据库管理系统中一个重要的概念&#xff0c;它定义了事务之间的可见性和影响。在多用户并发访问数据库时&#xff0c;隔离级别能够确保事务之间的相互独立性&#xff0c;避免数据不一致的问题。本文将深入探讨三种常见的并发问题&#xff1a;脏读、不可重复读…