[Algorithm][BFS][最短路问题][迷宫中离入口最近的出口][最小基因变化][单词接龙][为高尔夫比赛砍树]详细讲解

server/2024/9/23 11:20:16/

0.原理讲解

  • 最短路径里的常见问题
  • 本专题主要讲解边权为一的最短路问题
    • 边权全都相同即可,并非只能为一
  • 方法从起点开始,来一次BFS即可
  • 如何找出最短路径是多长呢?
    • 拓展的层数,就是最短路的长度
      请添加图片描述

1.迷宫中离入口最近的出口

1.题目链接


2.算法原理详解

  • 思路BFS
    • 从起点开始层序遍历,并且在遍历的过程中记录当前遍历的层数
      • 这样就能在找到出⼝的时候,得到起点到出⼝的最短距离
    • BFS解决迷宫问题,是最经典的做法

3.代码实现

class Solution 
{int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};
public:int nearestExit(vector<vector<char>>& maze, vector<int>& entrance) {int n = maze.size(), m = maze[0].size();vector<vector<bool>> visit(n, vector<bool>(m, false));visit[entrance[0]][entrance[1]] = true;queue<pair<int, int>> q;q.push({entrance[0], entrance[1]});// BFSint step = 0;while(q.size()){step++;int sz = q.size();while(sz--) // 本层{auto [a, b] = q.front();q.pop();// 将下一层入队列for(int i = 0; i < 4; i++){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < n && y >= 0 && y < m \&& maze[x][y] == '.' && !visit[x][y]){// 判断是否遇到出口if(x == 0 || x == n - 1 || y == 0 || y == m - 1){return step;}visit[x][y] = true;q.push({x, y});}}}}return -1;}
};

2.最小基因变化

1.题目链接


2.算法原理详解

  • 分析:如果将「每次字符串的变换」抽象成图中的「两个顶点和⼀条边」的话,问题就变成了「边权为 1 的最短路问题

  • 问题为什么可以这样转化成「边权为 1 的最短路问题

    • 从源字符串变到目标字符串,可以抽象成从起点到终点
    • 中间的每一次变换,都可以抽象成图中的「两个顶点和⼀条边」
    • 每次都只能变换一个字符,那么可以抽象成两个顶点间,权值均为1
      请添加图片描述
  • 如何枚举出所有的变化情况呢?

    • 直接暴力枚举每一个位置的每一个变化情况即可
  • 枚举出来的所有情况,都需要加入到队列里面吗?

    • 不需要,如果基因库中没有此次变化的结果,那么此次变化就不是一次合法的变化
  • 如何快速判断是否在基因库中存在?

    • hash<string>
  • 细节:用hash<string>来标记搜索过的状态


3.代码实现

int MinMutation(string startGene, string endGene, vector<string>& bank) 
{unordered_set<string> visit; // 用来标记已经搜索过的状态unordered_set<string> hash(bank.begin(), bank.end()); // 存储基因库string change = "ACGT"; // hash// 边界情况处理if(startGene == endGene){return 0;}if(!hash.count(endGene)){return -1;}queue<string> q;q.push(startGene);visit.insert(startGene);// BFSint ret = 0;while(q.size()){ret++;int sz = q.size();while(sz--){string str = q.front();q.pop();// 将下一层入队列// 暴力穷举所有的变化情况:Pfor(int i = 0; i < 8; i++){string tmp = str; // 细节:确保每次只变化一个位置for(int j = 0; j < 4; j++){tmp[i] = change[j];if(tmp == endGene){return ret;}if(hash.count(tmp) && !visit.count(tmp)){visit.insert(tmp);q.push(tmp);}}}}}return -1;
}

3.单词接龙

1.题目链接


2.算法原理详解

  • 分析:如果将「每次字符串的变换」抽象成图中的「两个顶点和⼀条边」的话,问题就变成了「边权为 1 的最短路问题

  • 问题为什么可以这样转化成「边权为 1 的最短路问题

    • 从源字符串变到目标字符串,可以抽象成从起点到终点
    • 中间的每一次变换,都可以抽象成图中的「两个顶点和⼀条边」
    • 每次都只能变换一个字符,那么可以抽象成两个顶点间,权值均为1
      请添加图片描述
  • 如何枚举出所有的变化情况呢?

    • 直接暴力枚举每一个位置的每一个变化情况即可
  • 枚举出来的所有情况,都需要加入到队列里面吗?

    • 不需要,如果字典中没有此次变化的结果,那么此次变化就不是一次合法的变化
  • 如何快速判断是否在字典中存在?

    • hash<string>
  • 细节:用hash<string>来标记搜索过的状态

3.代码实现

int LadderLength(string beginWord, string endWord, vector<string>& wordList) 
{unordered_set<string> visit;unordered_set<string> dictionary(wordList.begin(), wordList.end());if(!dictionary.count(endWord)){return 0;}queue<string> q;q.push(beginWord);visit.insert(beginWord);// BFSint count = 0;while(q.size()){count++;int sz = q.size();while(sz--){string str = q.front();q.pop();// 将下一层入队列// 暴力枚举所有可能情况:Pfor(int i = 0; i < beginWord.size(); i++){string tmp = str; // 细节:确保每次只更改一个位置for(char j = 'a'; j <= 'z'; j++){tmp[i] = j;if(dictionary.count(tmp) && !visit.count(tmp)){if(tmp == endWord){return ++count;}q.push(tmp);visit.insert(tmp);}}}}}return 0;
}

4.为高尔夫比赛砍树

  • 思路:将问题转化为若干个「迷宫问题」-> 从入口找出口
    • 先找出砍树的顺序
    • 然后按照砍树的顺序,⼀个⼀个的⽤BFS求出最短路径即可
class Solution 
{typedef pair<int, int> PII;int n, m;bool visit[50][50];// 方向向量数组int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};
public:int cutOffTree(vector<vector<int>>& forest) {n = forest.size(), m = forest[0].size();// 找出砍树的顺序vector<PII> trees;for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){if(forest[i][j] > 1){trees.push_back({i, j});}}}sort(trees.begin(), trees.end(), [&](const PII& p1, const PII& p2){return forest[p1.first][p1.second] < forest[p2.first][p2.second];});// 按照顺序砍树int ret = 0;int beginX = 0, beginY = 0;for(auto& [a, b] : trees){int step = BFS(forest, beginX, beginY, a, b);if(step == -1){return -1;}ret += step;beginX = a, beginY = b;}return ret;}// 解决单源权值为一的最短路径问题int BFS(vector<vector<int>>& forest, int beginX, int beginY, int endX, int endY){// 边界情况处理if(beginX == endX && beginY == endY){return 0;}memset(visit, false, sizeof visit); // 每次调用BFS都需要执行,否则影响下次BFSvisit[beginX][beginY] = true;queue<PII> q;q.push({beginX, beginY});int step = 0;while(q.size()){step++;int sz = q.size();while(sz--){auto [a, b] = q.front();q.pop();// 将下一层入队列for(int i = 0; i < 4; i++){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < n && y >= 0 && y < m \&& forest[x][y] && !visit[x][y]){if(x == endX && y == endY){return step;}visit[x][y] = true;q.push({x, y});}}}}return -1;}
};

http://www.ppmy.cn/server/35754.html

相关文章

【C++】学习笔记——list

文章目录 八、list1. list的介绍2. list的使用3. list的模拟实现4. list模拟实现的代码整合1. list.h2. test.cpp 未完待续 八、list list链接 1. list的介绍 是的&#xff0c; list 就是带头双向循环链表。 2. list的使用 通过 string 和 vector 的学习&#xff0c;我们差…

node.js对数据库的操作 之 query(查询)与pool(连接池)

一、Query&#xff08;查询&#xff09; &#xff08;1&#xff09;意义 query是指向数据库发送的一个命令或请求&#xff0c;以检索、更新、插入或删除数据。它是一个具体的SQL语句或NoSQL命令&#xff0c;用于从数据库中获取或修改数据。 &#xff08;2&#xff09;用途 …

Mysql数据在磁盘上的存储结构

一. 前言 一行数据的存储格式大致如下所示: 变长字段的长度列表&#xff0c;null值列表&#xff0c;数据头&#xff0c;column01的值&#xff0c;column02的值&#xff0c;column0n的值… 二. 变长字段 在MySQL里有一些字段的长度是变长的&#xff0c;是不固定的&#xff0c;…

为什么电子商务安全是速度和保护之间的平衡行为

微信搜索关注公众号网络研究观&#xff0c;获取更多信息。 电子商务世界是一把双刃剑。虽然它为企业和消费者提供了便利和可访问性&#xff0c;但它也为网络犯罪分子提供了诱人的目标。在这个不断变化的环境中&#xff0c;优先考虑安全不再是一种选择&#xff1b;而是一种选择&…

牛客网刷题 | BC78 KiKi说祝福语

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 2020年来到了&#…

淘宝扭蛋机小程序开发:开启你的惊喜之旅

一、扭出新世界&#xff0c;惊喜不断 在这个充满无限可能的数字时代&#xff0c;淘宝扭蛋机小程序为你带来了一种全新的购物与娱乐体验。扭蛋机&#xff0c;这个充满童趣和惊喜的玩具&#xff0c;如今在我们的小程序中焕发出新的活力&#xff0c;为你带来一波又一波的惊喜与快…

Labels and Databases for Mac:强大的标签与数据库管理工具

Labels and Databases for Mac是一款集标签制作与数据库管理于一体的强大工具&#xff0c;专为Mac用户打造&#xff0c;旨在提供高效、便捷的标签制作与数据管理体验。 这款软件拥有丰富的内置标签格式&#xff0c;用户可轻松创建各种标签、信封和卡片&#xff0c;满足个性化需…

基于React实现B站评论区

今天继续来学习一下React&#xff0c;使用React实现B站评论区&#xff0c;如下图&#xff1a; 在使用React开发类似B站评论区的功能时&#xff0c;我们需要考虑以下几个关键点来构建一个基本的评论系统&#xff1a; 1. 设计组件结构 首先&#xff0c;设计组件结构是关键。至少…