算法笔记(十三)——BFS 解决最短路问题

news/2024/10/11 18:11:09/

文章目录

  • 迷宫中离入口最近的出口
  • 最小基因变化
  • 单词接龙
  • 为高尔夫比赛砍树

BFS 解决最短路问题

BFS(广度优先搜索) 是解决最短路径问题的一种常见算法。在这种情况下,我们通常使用BFS来查找从一个起始点到目标点的最短路径。


迷宫中离入口最近的出口

题目:迷宫中离入口最近的出口

在这里插入图片描述

思路

图论中边路权值为1的情况,利用层序遍历来解决是最经典的做法。
从起点开始层序遍历,在遍历的过程中记录当前遍历的层数

C++代码

class Solution 
{int dx[4] = {0, 0, 1, -1};int dy[4] = {-1, 1, 0, 0};public:int nearestExit(vector<vector<char>>& maze, vector<int>& entrance) {int m = maze.size(), n = maze[0].size();vector<vector<bool>> visited(m, vector<bool>(n, false));int ret = 0; queue<pair<int, int>> q;  q.push({entrance[0], entrance[1]});visited[entrance[0]][entrance[1]] = true;while(q.size()){ret++;int sz = q.size();for(int i = 0; i < sz; i++){auto [a, b] = q.front(); q.pop();for(int k = 0; k < 4; k++){int x = a + dx[k], y = b + dy[k];if(0 <= x && x < m && 0 <= y && y < n && maze[x][y] == '.' && !visited[x][y]){if(x == 0 || x == m - 1 || y == 0 || y == n - 1) return ret;q.push({x, y});visited[x][y] = true;}}}}return -1;}
};

最小基因变化

题目:最小基因变化

在这里插入图片描述
思路

转化成边路权值为1的图论问题

  • unordered_set<string> hash(bank.begin(), bank.end());来存储基因库,快速判断该基因是否存在于基因库

  • 枚举出的每一个位置,我们先判断其是否为合法基因(如果基因库中有并且该基因没有被访问)

  • 用一个unordered_set<string> visited;用于标记是否访问过该基因序列

  • 用BFS,尝试每个位置可能变异后得结果,如果变异后的基因是合法基因,就加入队列中,并标记为已访问

C++代码

class Solution 
{
public:int minMutation(string startGene, string endGene, vector<string>& bank) {unordered_set<string> hash(bank.begin(), bank.end()); // 创建一个hash方便判断该基因序列是否合法unordered_set<string> visited; // 用于标记是否访问过该基因序列string change = "ACGT"; // 可能的基因变异字符if(startGene == endGene) return 0; // 起始基因和目标基因相同,不用改变if(!hash.count(endGene)) return -1; // 目标基因不在基因库,返回-1queue<string> q;q.push(startGene); // 起始基因入队visited.insert(startGene); // 标记起始基因被访问int ret = 0;while(!q.empty()){int sz = q.size();ret++;while(sz--){string t = q.front();q.pop();for(int i = 0; i < 8; i++) // 遍历每个位置{string tmp = t;for(int j = 0; j < 4; j++) // 每个位置更改 4 次{tmp[i] = change[j];// 如果基因库中有并且该基因没有被访问,则为合法基因if(hash.count(tmp) && !visited.count(tmp)) {// 合法基因等于目标基因返回结果if(tmp == endGene)return ret;// 合法基因入队并且标记访问过了q.push(tmp);visited.insert(tmp);}}}}}return -1;}
};

单词接龙

题目:单词接龙

在这里插入图片描述

思路

和上一题的思路一毛一样,只不过上题每个位置变化只有四种可能,而这题每个位置的变换有二十六种可能性

C++代码

class Solution 
{
public:int ladderLength(string beginWord, string endWord, vector<string>& wordList) {unordered_set<string> visited; // 记录该单词是否访问过了unordered_set<string> hash(wordList.begin(), wordList.end());if (beginWord == endWord) return 1; // 起始单词和目标单词相同,不用改变if (!hash.count(endWord)) return 0; // 目标单词不在wordList,返回 0 queue<string> q;q.push(beginWord); // 起始单词入队visited.insert(beginWord); // 标记起始单词被访问int ret = 1;while(!q.empty()){ret++;int sz = q.size();while(sz--){string t = q.front();q.pop(); for(int i = 0; i < t.size(); i++) // 遍历单词的每个位置{string tmp = t;for(char ch = 'a'; ch <= 'z'; ch++) // 每个位置更改 26 次{tmp[i] = ch;// 判断是否为合法单词if(hash.count(tmp) && !visited.count(tmp)){if (tmp == endWord) return ret;q.push(tmp);visited.insert(tmp);}}}}}return 0;}
};

为高尔夫比赛砍树

题目:为高尔夫比赛砍树

在这里插入图片描述
思路

其实本题就是多次的迷宫问题累计求和,不停的变换起始位置(x, y)以及终止位置(nx, ny)

  • 遍历森林,将树木的位置加入 trees数组中
  • 树木的高度进行排序
  • BFS计算起始位置(x, y)以及终止位置(nx, ny)的距离
  • 累加步数,并更新起始位置(x, y)

C++代码

class Solution 
{int dx[4] = {0, 0, 1, -1};int dy[4] = {1, -1, 0, 0};int m, n;bool visited[51][51];int bfs(vector<vector<int>>& forest, int x, int y, int nx, int ny) {if (x == nx && y == ny) return 0;  // 如果起始位置和目标位置相同,步数为0queue<pair<int, int>> q;memset(visited, 0, sizeof visited);q.push({x, y});visited[x][y] = true;int ret = 0;while(!q.empty()){   ret++;int sz = q.size();while(sz--){auto [a, b] = q.front();q.pop();for(int k = 0; k < 4; k++){int x = a + dx[k], y = b + dy[k];if(0 <= x && x < m && 0 <= y && y < n && forest[x][y] && !visited[x][y]){if (x == nx && y == ny) // 如果到达目标位置,返回步数return ret;q.push({x, y});visited[x][y] = true;}}}}return -1;}public:int cutOffTree(vector<vector<int>>& forest) {m = forest.size(), n = forest[0].size();// 将树的坐标存放起来vector<pair<int, int>> trees;for(int i = 0; i < m; i++)for(int j = 0; j < n; j++)if (forest[i][j] > 1)   trees.push_back({i, j});// 根据树木的高度进行排序sort(trees.begin(), trees.end(), [&](const pair<int, int>& p1, const pair<int, int>& p2) {return forest[p1.first][p1.second] < forest[p2.first][p2.second];});int x = 0, y = 0; // 起始位置(0, 0)int ret = 0;// 从小到大遍历for(auto& [nx, ny] : trees){int step = bfs(forest, x, y, nx, ny);if(step == -1) return -1;ret += step;x = nx, y = ny; // 更新起始位置}return ret;}
};

http://www.ppmy.cn/news/1537566.html

相关文章

tp6的系统是如何上架的

TP6&#xff08;ThinkPHP6&#xff09;的系统上架过程&#xff0c;通常指的是将基于ThinkPHP6框架开发的应用程序部署到生产环境&#xff0c;并使其可以通过互联网访问。以下是一个大致的上架流程&#xff0c;包括准备工作、部署步骤以及后续维护等方面&#xff1a; 一、准备工…

【计算机网络】CDN

CDN&#xff08;Content Delivery Network&#xff0c;内容分发网络&#xff09;是一种分布式的服务器网络&#xff0c;旨在通过将内容缓存到多个地理位置的服务器上&#xff0c;加速内容的分发和传递。CDN 的主要目的是减少用户访问网站时的延迟&#xff0c;提升用户体验&…

Android 14.0 Launcher3 app图标和hotseat 添加背景(焦点选中背景)

1.概述 在14.0的系统产品rom定制化开发中,进行Tv设备定制化开发中,配置的有遥控器需要使用遥控器来移动来控制点击功能,所以需要给app 的Icon 和hotseat 添加背景来显示选中状态原生的Launcher的背景没有支持遥控器的焦点事件,所以就需要在Launcher3中给Item 添加默认背景…

Linux——cp-mv-rm命令

cp命令 复制文件 cp test01.txt test02.txt 复制文件夹 cp -r hsy01 hsy02 mv命令 移动文件/文件夹 rm命令 删除文件 rm test.txt 删除文件夹&#xff08;目录 rm -r hsy01 通配符 * 匹配任意内容 注意* 位置 强制删除-f root超级管理员

贝壳Android面试题及参考答案

详细说Final关键字 在编程语言中,final关键字具有重要的作用。以下为你详细介绍final关键字: 一、final关键字的主要作用 修饰变量 当final修饰基本数据类型变量时,该变量的值一旦被初始化就不能再被改变。例如:final int num = 10;num = 20; // 这会导致编译错误当final修…

【SQL】掌握SQL查询技巧:数据分组与排序

目录 1. GROUP BY1.1 定义与用途1.2 示例说明1.3 注意事项1.4 可视化示例 2. ORDER BY2.1 定义与用途2.2 升序说明&#xff08;默认&#xff09;2.3 降序排序2.4 多列排序2.5 可视化示例 3. GROUP BY 与 ORDER BY 的结合使用4. 可视化示例总结 在数据库管理中&#xff0c;SQL&a…

vue-cli老项目继续优化:json压缩神器 compress-json

前言 上文讲到一个 vue-cli 带脚本生成内容的老项目的打包时间已经从 40min &#xff0c;优化到 12min &#xff0c;再到 9min 。 还有可以考虑的方式包含缩小脚本体积、依赖分包、构建的缓存等等。 那么本文就来讨论缩小脚本体积的方式。 分析 前文已知&#xff0c;生成的…

Linux CentOS stream9配置本地yum源

在Linux系统中,yum源配置是一个重要的环节。把系统安装时配置的国外yum源转换为国内yum源,能够帮助系统快速安装软件包。对于网络环境不稳定或无法联网的系统,配置本地yum源,可以让用户在离线状态下也能进行软件包的安装,十分重要。 一、国内源 在使用Linux的日常工作中…