【C++算法】BFS解决单源最短路问题相关经典算法题

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

首先我们可以将这道题目简化一下,可以往我们这一章的主题上面来想想。

我们利层序遍历来解决最短路径问题,是最经典的做法。我们可以从起点开始层序遍历, 并组在遍历的过程中记录当前遍历的层数。这样就能在找到出口的时候,得到起点到出口的最短距离,话不多说,我们直接来上思路:

直接上代码:

class Solution {
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    bool vis[101][101] = {false};
public:
    int nearestExit(vector<vector<char>>& maze, vector<int>& entrance) {
        int m = maze.size(); // 横坐标
        int n = maze[0].size(); // 纵坐标
        int step = 0; // 记录结果
        
        queue<pair<int,int>> q;
        q.push({entrance[0],entrance[1]}); // 起始位置进队列
        vis[entrance[0]][entrance[1]] = true;  // 起始位置标记为true

        while(!q.empty())
        {
            step++;
            int sz = q.size();
            for(int i = 0; i < sz; i++)
            {
                auto [a, b] = q.front();
                q.pop();
                for(int i = 0; i < 4; i++)
                {
                    int x = a + dx[i];
                    int y = b + dy[i];
                    if(x >= 0 && x < m && y >= 0 && y < n && maze[x][y] == '.' && !vis[x][y])
                    {
                        if(x == 0 || x == m - 1 || y == 0 || y == n - 1) return step;
                        // 判断是否已经到达出⼝
                        vis[x][y] = true;
                        q.push({x,y});
                    }
                }
            } 
        }
        return -1;
    }
};

2.最小基因变化

首先我们看到这个题目,真的是难从下手,既然我们这章是最短路径,我们可以尝试从这方面来考虑考虑,我们可以考虑尝试来转化一下哈。

直接上思路:

直接上代码:

class Solution {
public:
    int minMutation(string startGene, string endGene, vector<string>& bank) {
        unordered_set<string> vis; // 用来标记已经搜索过的状态
        unordered_map<string,int> hash; // 存储基因库中的字符串
        for(auto& e : bank)
            hash[e]++;
        char change[4] = {'A','C','G','T'};
        // 处理边界情况
        if(startGene == endGene) return 0;
        if(!hash.count(endGene)) return -1;

        queue<string> q;
        q.push(startGene);
        vis.insert(startGene); //该字符串已经被使用过啦

        int ret = 0;
        while(q.size())
        {
            ret++;
            int sz = q.size();
            while(sz--)
            {
                auto front = q.front();
                q.pop();
                for(int i = 0; i < front.size(); i++)
                {
                    string tmp = front;
                    for(int j = 0; j < 4; j++)
                    {
                        // front[i] = change[j]; // ???
                        // 此时我们不能在原字符串上修改,会造成一次修改多个字符
                        tmp[i] = change[j];
                        // 判断合法性
                        // 此时我们修改依然是startGene,但是此时已经标记不进队列
                        if(hash.count(tmp) && !vis.count(tmp)) // 入队列
                        {
                            if(tmp == endGene) return ret;
                            q.push(tmp);
                            vis.insert(tmp);
                        }
                    }
                }
            }
        }
        return -1;
    }
};

3.单词接龙

首先看到这个题目可以总结转化两个规律:

⭐从beginWord到endWord每次只能修改一个字符,并且每次中从'a'-'z'中挑选一个进行修改

⭐每次修改的字符串必须在wordList中

所以我们会发现和上面那道题的基本是一模一样的,思路和上面一模一样,唯一的是区别是不是统计步数,而是过程中单词的数量,解决这个也很简单,只需将步数+1即可,直接上代码:

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        unordered_set<string> vis; // 标记已经搜索过的单词
        unordered_set<string> hash(wordList.begin(),wordList.end());
        // 处理边界情况
        if(beginWord == endWord) return 1;
        if(!hash.count(endWord)) return 0;

        queue<string> q;
        q.push(beginWord);
        vis.insert(beginWord);
        int ret = 0;

        while(q.size())
        {
            ret++;
            int sz = q.size();
            for(int i = 0; i < sz; i++)
            {
                string t = q.front();
                q.pop();
                for(int i = 0; i < t.size(); i++)
                {
                    string tmp = t;
                    for(char ch = 'a'; ch <= 'z'; ch++)
                    {
                        tmp[i] = ch;
                        if(hash.count(tmp) && !vis.count(tmp))
                        {
                            // 找到尾串,直接返回结果
                            if(tmp == endWord) return ret + 1;
                            q.push(tmp);
                            vis.insert(tmp);
                        }
                    }
                }
            }
        }
        return 0;
    }
};

4.为高尔夫比赛砍树

注意:本题是要求砍树必须从低到高砍掉所有的树

所以这道题目的思路和本章的第一个题目的思路是差不多的思路,只不过本题需要调用多个最短路径的代码即可解决,我们直接来上代码:

class Solution {
    bool vis[51][51] = {false};
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    int m;
    int n;
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});
        // 根据树的长度进行排序 - 从小到大
        // 使用lambda进行排序
        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 ax = 0, ay = 0; //起始位置
        int ret = 0;
        for(auto& [a, b] : trees)
        {
            int step = bfs(forest, ax, ay, a, b);
            // 走不到直接返回-1
            if(step == -1) return -1;
            ret += step;
            ax = a;
            ay = b;
        }
        return ret;
    }
    // 传入起点和终点的坐标,返回最短路径  
    int bfs(vector<vector<int>>& forest, int ax, int ay, int bx, int by)
    {
        // 处理边界情况
        if(ax == bx && ay == by) return 0;

        queue<pair<int,int>> q;
        // 注意每次都需要清理vis数组
        memset(vis, false, sizeof(vis));
        q.push({ax,ay});
        vis[ax][ay] = true;
        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];
                    int y = b + dy[i];
                    if(x >=0 && x <= m - 1 && y >= 0 && y <= n - 1 && !vis[x][y] && forest[x][y])
                    {
                        if(x == bx && y == by) return step;
                        q.push({x,y});
                        vis[x][y] = true;
                    }
                }
            }
        }
        return -1;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于open3d对kitti数据集检测结果可视化

前言 KITTI数据集是自动驾驶和计算机视觉领域中一个广泛使用的基准数据集&#xff0c;它提供了丰富的传感器数据&#xff0c;包括激光雷达、相机和GPS等。Open3D是一个功能强大的3D数据处理和可视化库&#xff0c;支持多种3D数据格式。本文将介绍如何使用Open3D对KITTI数据集的…

html简述——part1

HTML概述 HTML&#xff08;HyperText Markup Language&#xff09;是一种用于创建网页的标准标记语言&#xff0c;具体指超文本标记语言。它不是一种编程语言&#xff0c;而是一种标记语言&#xff0c;用于描述网页的结构和内容。通过HTML&#xff0c;开发者可以定义网页的标题…

sky walking日志采集以及注意事项

文章目录 1&#xff0c;sky walking日志采集功能概述2&#xff0c;采集log4j2日志3&#xff0c;采集logback日志4&#xff0c;效果展示5&#xff0c;注意事项 1&#xff0c;sky walking日志采集功能概述 在介绍Sky walking日志采集功能之前&#xff0c;最好在系统学习一遍日志…

使用FP8加速PyTorch训练的两种方法总结

在PyTorch中&#xff0c;FP8&#xff08;8-bit 浮点数&#xff09;是一个较新的数据类型&#xff0c;用于实现高效的神经网络训练和推理。它主要被设计来降低模型运行时的内存占用&#xff0c;并加快计算速度&#xff0c;同时尽量保持训练和推理的准确性。虽然PyTorch官方在标准…

primeflex样式库笔记 Display相关的案例

回顾 宽度设置的基本总结 w-full&#xff1a;表示widtdh&#xff1a;100%&#xff1b;占满父容器的宽度。 w-screen&#xff1a;表示占满整个屏幕的宽度。 w-1到w-12&#xff0c;是按百分比划分宽度&#xff0c;数字越大&#xff0c;占据的比例就越大。 w-1rem到w-30rem&…

欧拉函数、快速幂、扩展欧几里得算法、中国剩余定理和高斯消元

欧拉函数 给定 n 个正整数 ai&#xff0c;请你求出每个数的欧拉函数。 欧拉函数的定义1∼N 中与 N 互质的数的个数被称为欧拉函数&#xff0c;记为 ϕ(N)。 若在算数基本定理中&#xff0c;Np1a11p2a2…pmm&#xff0c;则&#xff1a;ϕ(N) Np1−1/p1p2−1/p2…pm−1/pm 输…

WPF之打印与预览

目录 1&#xff0c;打印设置与管理。 1.1&#xff0c;引入程序集&#xff1a; 1.2&#xff0c;主要管理类介绍&#xff1a; 1.3&#xff0c;应用&#xff1a; 1.4&#xff0c;效果。 1.5&#xff0c;Demo链接。 2&#xff0c;打印。 2.1&#xff0c;主要参与打印的类与…

Mac JDK和SDK环境变量配置

一、Java JDK配置 1.下载并安装Java jdk1.8及以上&#xff0c;这个可以在网上自行搜索下载&#xff0c;这里不在详细描述 2.如果不知道JAVA_HOME的安装路径&#xff0c;可以输入命令查看&#xff1a;/usr/libexec/java_home -V &#xff0c;如图 3.在终端输入命令&#xff1…

uniapp微信小程序解决open-type获取用户头像,返回临时路径问题!

解决 open-type 为 chooseAvatar&#xff0c;返回临时路径问题 文章目录 解决 open-type 为 chooseAvatar&#xff0c;返回临时路径问题效果图Demo获取头像回调数据结构效果图解决方式上传到服务器转base64 基于微信小程序获取头像昵称规则调整后&#xff0c;当小程序需要让用户…

CS 下载安装详解

目录 CS简介&#xff1a; CS下载地址&#xff1a; CS的安装&#xff1a; CS简介&#xff1a; CS为目前渗透中常用的一款工具&#xff0c;它的强大在于控制windows木马&#xff0c;CS主要控制windows木马。 CS下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/…

华为OD机试【找出通过车辆最多颜色】(java)(100分)

1、题目描述 在一个狭小的路口&#xff0c;每秒只能通过一辆车&#xff0c;假设车辆的颜色只有 3 种&#xff0c;找出 N 秒内经过的最多颜色的车辆数量。 三种颜色编号为0 &#xff0c;1 &#xff0c;2。 2、输入描述 第一行输入的是通过的车辆颜色信息[0,1,1,2] &#xff0…

huggingface笔记: accelerate estimate-memory 命令

探索可用于某一机器的潜在模型时&#xff0c;了解模型的大小以及它是否适合当前显卡的内存是一个非常复杂的问题。为了缓解这个问题&#xff0c;Accelerate 提供了一个 命令行命令 accelerate estimate-memory。 accelerate estimate-memory {MODEL_NAME} --library_name {LIBR…

AIGC-风格迁移-style Injection in Diffusion-CVPR2024HighLight-论文精度

Style Injection in Diffusion: A Training-free Approach for Adapting Large-scale Diffusion Models for Style Transfer-CVPR2024HighLight 代码&#xff1a;https://github.com/jiwoogit/StyleID 论文&#xff1a;https://jiwoogit.github.io/StyleID_site/ 为了解决风格迁…

Oracle的安装以及一些相关问题

系列文章目录 Oracle的安装以及一些相关问题 文章目录 系列文章目录前言一、Oracle的安装二、常用命令三、误删dbf四、PLSQL乱码五、oracle更换数据库字符集总结 前言 一段时间没更新&#xff0c;主要最近一直在找工作&#xff0c;最终还是顺着春招找到工作了&#xff0c;现在…

使用nvm管理nodejs多个版本

在工作中&#xff0c;可能会遇到同时使用vue2和vue3开发项目&#xff0c;但他们的nodejs版本又不同&#xff0c;给你带来了困扰&#xff0c;不知道怎么办&#xff1f;这时就可以使用nvm管理多个nodejs版本 第一步&#xff1a;先去github上面下载nvm 这是下载地址&#xff1a;…

大语言模型的工程技巧(四)——梯度检查点

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 本文将讨论如何利用梯度检查点算法来减少模型在训练时候&#xff08;更准确地说是运行反向传播算法时&#xff09;的内存开支。…

C++_string简单源码剖析:模拟实现string

文章目录 &#x1f680;1.构造与析构函数&#x1f680;2.迭代器&#x1f680;3.获取&#x1f680; 4.内存修改&#x1f680;5. 插入&#x1f680;6. 删除&#x1f680;7. 查找&#x1f680;8. 交换swap&#x1f680;9. 截取substr&#x1f680;10. 比较符号重载&#x1f680;11…

【IC设计】牛客网-序列检测习题总结

文章目录 状态机基础知识VL25 输入序列连续的序列检测VL26 含有无关项的序列检测VL27 不重叠序列检测VL28 输入序列不连续的序列检测参考资料 状态机基础知识 VL25 输入序列连续的序列检测 timescale 1ns/1ns module sequence_detect(input clk,input rst_n,input a,output re…

vue三级联动组件

背景 项目中经常出现三级下拉框组件的要求&#xff0c;这种组件其中一级发生变化&#xff0c;子级的组件就会发生变化如果这一个组件&#xff0c;单独作为搜索条件使用&#xff0c;很好写&#xff0c;同时作为搜索条件和form回写组件&#xff0c;回显就比较困难 子组件代码 将与…

一分钟带你创建百万测试数据,玩转软件测试

准备测试数据是软件测试中非常重要的一个环节&#xff0c;无论是手工测试、动化测试还是性能测试&#xff0c;生成大量测试数据以评估性能是一项重要任务。 然而&#xff0c;寻找合适的测试数据并确保其质量常常是一项繁琐且耗时的工作。 先来看一下准备测试数据常见的四类方法…