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

news2024/11/25 4:28:54

文章目录

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

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; // 目标基因不在基因库,返回-1

        queue<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;  // 如果起始位置和目标位置相同,步数为0

        queue<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.coloradmin.cn/o/2195384.html

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

相关文章

can 总线入门———can简介硬件电路

文章目录 0. 前言1. CAN简介2. 主流通讯协议对比3. CAN 硬件电路4. CAN 电平标准5. CAN 收发器 0. 前言 博客内容来自B站上CAN总线入门教程视频讲解&#xff0c;博客中的插图和内容均为视频中的内容。视频链接 CAN总线入门教程 1. CAN简介 先来看看一它名字的意思&#xff0c…

Redis 缓存策略详解:提升性能的四种常见模式

在现代分布式系统中&#xff0c;缓存是提升性能和减轻数据库负载的关键组件。Redis 作为一种高性能的内存数据库&#xff0c;被广泛应用于缓存层。本文将深入探讨几种常用的 Redis 缓存策略&#xff0c;包括旁路缓存模式&#xff08;Cache-Aside Pattern&#xff09;、读穿透模…

强化学习入门到不想放弃-4

上回的地址&#xff1a;强化学习入门到不想放弃-3 (qq.com) 上上回地址&#xff1a;强化学习入门到不想放弃-2 (qq.com) 上上上回地址&#xff1a;强化学习入门到不想放弃-1 (qq.com) 好久没更新了&#xff0c;也是不知道写啥啊&#xff0c;&#xff08;有些文章刚写了就被有些…

鸽笼原理与递归 - 离散数学系列(四)

目录 1. 鸽笼原理 鸽笼原理的定义 鸽笼原理的示例 鸽笼原理的应用 2. 递归的定义与应用 什么是递归&#xff1f; 递归的示例 递归与迭代的对比 3. 实际应用 鸽笼原理的实际应用 递归的实际应用 4. 例题与练习 例题1&#xff1a;鸽笼原理应用 例题2&#xff1a;递归…

三、Python基础语法(注释、三种波浪线、变量)

一、注释 注释是对代码进行解释说明的文字&#xff0c;不会被解释器执行&#xff0c;可以更方便阅读代码和了解代码的作用。 1.单行注释 使用#开头的文字就是注释&#xff0c;可以使用快捷键Ctrl / 2.多行注释 多行注释就是注释的内容&#xff0c;可以换行书写&#xff0c…

集智书童 | 用于时态动作检测的预测反馈 DETR !

本文来源公众号“集智书童”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;用于时态动作检测的预测反馈 DETR ! 视频中的时间动作检测&#xff08;TAD&#xff09;是现实世界中的一个基本且具有挑战性的任务。得益于 Transformer …

提升 CI/CD 稳定性:Jenkins 开机自检与推送通知

简介&#xff1a;Jenkins 是一个广泛使用的开源自动化服务器&#xff0c;常用于持续集成和持续交付。在某些情况下&#xff0c;服务器重启可能导致 Jenkins 构建任务中断或失败。为了解决这个问题&#xff0c;可以使用一个自检服务&#xff0c;定期检查系统的启动时间&#xff…

3559 pcie配置流程

目录 EP配置 uboot配置 uboot代码修改 内核代码修改 带宽配置 带宽查看 硬件管脚配置 EP配置 uboot配置 1)make CROSS_COMPILE=aarch64-himix100-linux- hi3559av100_emmc_defconfig 2) make menuconfig CROSS_COMPILE=aarch64-himix100-linux- 修改配置: 3) 合入…

一种将RAG、KG、VS、TF结合增强领域LLM性能的框架

SMART-SLIC框架&#xff1a;旨在将RAG结合向量存储&#xff08;Vector Stores&#xff09;、知识图谱&#xff08;Knowledge Graphs&#xff09;和张量分解&#xff08;Tensor Factorization&#xff09;来增强特定领域的大型语言模型&#xff08;LLMs&#xff09;的性能。 SM…

codetop标签动态规划大全C++讲解(二)!!动态规划刷穿地心!!学吐了家人们o(╥﹏╥)o

一篇只有十题左右&#xff0c;写少一点好复习 1.目标和2.分割等和子集3.完全平方数4.比特位计数5.石子游戏6.预测赢家7.不同的二叉搜索树8.解码方法9.鸡蛋掉落10.正则表达式匹配11.通配符匹配12.交错字符串 1.目标和 给你一个非负整数数组 nums 和一个整数 target 。 向数组中…

01-python+selenium自动化测试-基础学习

前言 基于python3和selenium3做自动化测试&#xff0c;俗话说&#xff1a;工欲善其事必先利其器&#xff1b;没有金刚钻就不揽那瓷器活&#xff0c;磨刀不误砍柴工&#xff0c;因此你必须会搭建基本的开发环境&#xff0c;掌握python基本的语法和一个IDE来进行开发&#xff0c…

短剧系统源码短剧平台开发(H5+抖小+微小)部署介绍流程

有想法加入国内短剧赛道的请停下脚步&#xff0c;耐心看完此篇文章&#xff0c;相信一定会对您有所帮助的&#xff0c;下面将排序划分每一个步骤&#xff0c;短剧源码、申请资料、服务器选择、部署上架到正常运行等几个方面&#xff0c;整理了一些资料&#xff0c;来为大家举例…

中广核CGN25届校招网申SHL测评题库、面试流程、招聘对象,内附人才测评认知能力真题

​中国广核集团校园招聘在线测评攻略&#x1f680; &#x1f393; 校园招聘对象 2024届、2025届海内外全日制应届毕业生&#xff0c;大专、本科、硕士、博士&#xff0c;广核集团等你来&#xff01; &#x1f4c8; 招聘流程 投递简历 简历筛选 在线测评&#xff08;重点来啦…

C++ 算法学习——1.6 前缀和与二维前缀和算法

前缀和算法&#xff08;Prefix Sum Algorithm&#xff09;&#xff1a; 概念&#xff1a;前缀和算法通过在遍历数组时计算前缀和&#xff08;从数组的第一个元素开始累加到当前元素的和&#xff09;&#xff0c;可以在O(1)时间内得到任意区间的子数组和&#xff0c;而不需要重复…

告别音乐小白!字节跳动AI音乐创作工具,让你一键变作曲家!

还在羡慕别人能创作动听的音乐&#xff1f;五音不全的你&#xff0c;也梦想着谱写属于自己的乐章&#xff1f;现在&#xff0c;机会来了&#xff01;字节跳动推出了一款AI音乐创作工具——抖音推出的海绵音乐&#xff0c;它能让你轻松一键创作音乐&#xff0c;即使是“音乐小白…

海外科技新闻媒体与商业媒体:垂直网站的魅力与软文分发

海外科技新闻媒体与商业媒体&#xff1a;垂直网站的魅力与软文分发 在信息爆炸的时代&#xff0c;如何有效地传递品牌信息并提高知名度成为了许多企业的重要课题。在这个过程中&#xff0c;海外科技新闻媒体与商业媒体的垂直网站扮演了重要角色&#xff0c;而软文分发则因其独特…

笔试题总结

1.对于线性表的描述&#xff1a;存储空间不一定是连续&#xff0c;且各元素的存储顺序是任意的 2.虚函数的定义&#xff1a;函数的返回值参数不定&#xff0c; 声明&#xff1a; 类型&#xff0c;返回这类型 名字&#xff08;&#xff09;&#xff1b; 例如声明一个虚函数&a…

计算机毕业设计 基于Python的豆果美食推荐系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

JavaScript(JS)基础(一)

1、JavaScript&#xff08;JS&#xff09;简介 JavaScript 是一门跨平台、面向对象的脚本语言&#xff0c;它能使网页可交互&#xff08;例如拥有复杂的动画&#xff0c;可点击的按钮&#xff0c;通俗的菜单等&#xff09;。另外还有高级的服务端 Javascript 版本&#xff0c;例…

1.Python 引入(字面量、注释、变量、数据类型、数据类型转换、标识符、运算符、字符串扩展)

一、字面量 1、基本介绍 在代码中&#xff0c;被写直接下来的、不需要通过变量存储的值&#xff0c;称之为字面量 2、常用值类型 类型说明数字&#xff08;Number&#xff09;整数&#xff08;int&#xff09;&#xff0c;例如&#xff1a;10、-10浮点数&#xff08;float&…