【优选算法之BFS】No.15--- 经典BFS解决FloodFill算法和解决最短路问题

news2024/12/23 0:29:32

文章目录

  • 前言
  • 一、BFS解决FloodFill算法示例:
    • 1.1 图像渲染
    • 1.2 岛屿数量
    • 1.3 岛屿的最⼤⾯积
    • 1.4 被围绕的区域
  • 二、BFS解决最短路问题
    • 2.1 迷宫中离⼊⼝最近的出⼝
    • 2.2 最⼩基因变化
    • 2.3 单词接⻰
    • 2.4 为⾼尔夫⽐赛砍树


前言

在这里插入图片描述

👧个人主页:@小沈YO.
😚小编介绍:欢迎来到我的乱七八糟小星球🌝
📋专栏:优选算法
🔑本章内容:BFS解决FloodFill算法+BF解决解决最短路问题
记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~


一、BFS解决FloodFill算法示例:

1.1 图像渲染

  1. 题⽬链接:733. 图像渲染

  2. 题⽬描述:
    在这里插入图片描述

  3. 算法思路:
    可以利⽤「深搜」或者「宽搜」,遍历到与该点相连的所有「像素相同的点」,然后将其修改成指定的像素即可。

  4. C++代码

class Solution {
    typedef pair<int,int> PII;
    int dx[4]={0,0,-1,1};
    int dy[4]={-1,1,0,0};
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) 
    {
        int prev=image[sr][sc];
        if(prev==color)return image;
        int n=image.size(),m=image[0].size();
        queue<PII> q;
        image[sr][sc]=color;
        q.push({sr,sc});
        while(!q.empty())
        {
            auto[a,b]=q.front();
            q.pop();
            for(int k=0;k<4;k++)
            {
                int x=a+dx[k],y=b+dy[k];
                if(x>=0&&x<n&&y>=0&&y<m&&image[x][y]==prev)
                {
                    image[x][y]=color;
                    q.push({x,y});
                }
            }
        }
        return image;
    }
};

1.2 岛屿数量

  1. 题⽬链接:200. 岛屿数量
  2. 题⽬描述:
    在这里插入图片描述
  3. 算法思路:
    遍历整个矩阵,每次找到「⼀块陆地」的时候:
    • 说明找到「⼀个岛屿」,记录到最终结果 ret ⾥⾯;
    • 并且将这个陆地相连的所有陆地,也就是这块「岛屿」,全部「变成海洋」。这样的话,我们下次遍历到这块岛屿的时候,它「已经是海洋」了,不会影响最终结果。
    • 其中「变成海洋」的操作,可以利⽤「深搜」和「宽搜」解决,其实就是 733. 图像渲染 这道题~
    这样,当我们,遍历完全部的矩阵的时候, ret 存的就是最终结果。
  4. C++代码
class Solution {
    typedef pair<int,int> PII;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int n,m;
    int cnt=0;
public:
    void bfs(int i,int j,vector<vector<char>>& grid)
    {
        queue<PII> q;
        q.push({i,j});
        while(!q.empty())
        {
            auto[a,b]=q.front();
            q.pop();
            for(int k=0;k<4;k++)
            {
                int x=a+dx[k],y=b+dy[k];
                if(x>=0&&x<n&&y>=0&&y<m&&grid[x][y]=='1')
                {
                    q.push({x,y});
                    grid[x][y]='0';
                }
            }
        }
    }
    int numIslands(vector<vector<char>>& grid) 
    {
        n=grid.size();m=grid[0].size();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(grid[i][j]=='1')
                {
                    grid[i][j]='0';
                    bfs(i,j,grid);
                    cnt++;
                }
            }
        }
        return cnt;
    }
};

1.3 岛屿的最⼤⾯积

  1. 题⽬链接:695. 岛屿的最⼤⾯积
  2. 题⽬描述:
    在这里插入图片描述
  3. 算法思路:
    • 遍历整个矩阵,每当遇到⼀块⼟地的时候,就⽤「深搜」或者「宽搜」将与这块⼟地相连的「整个岛屿」的⾯积计算出来。
    • 然后在搜索得到的「所有的岛屿⾯积」求⼀个「最⼤值」即可。
    • 在搜索过程中,为了「防⽌搜到重复的⼟地」:
    ◦ 可以开⼀个同等规模的「布尔数组」,标记⼀下这个位置是否已经被访问过;
    ◦ 也可以将原始矩阵的 1 修改成 0 ,但是这样操作会修改原始矩阵。
  4. C++代码
class Solution {
    typedef pair<int,int> PII;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int n,m;
    int ret=0,maxsum=0;
    int flag[55][55]={0};//标记访问过的点
public:
    int bfs(int i,int j,vector<vector<int>>& grid)
    {
        queue<PII> q;
        q.push({i,j});
        int ret=0;
        while(!q.empty())
        {
            auto[a,b]=q.front();
            q.pop();
            for(int k=0;k<4;k++)
            {
                int x=a+dx[k],y=b+dy[k];
                if(x>=0&&x<n&&y>=0&&y<m&&grid[x][y]==1&&flag[x][y]==0)
                {
                    q.push({x,y});
                    //grid[x][y]=0;
                    flag[x][y]=1;
                }
            }
            ret++;
        }
        return ret;
    }
    int maxAreaOfIsland(vector<vector<int>>& grid) 
    {
        n=grid.size();m=grid[0].size();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(grid[i][j]==1&&flag[i][j]==0)
                {
                    //grid[i][j]=0;
                    flag[i][j]=1;
                    int cnt=bfs(i,j,grid);
                    maxsum=max(maxsum,cnt);
                }
            }
        }
        return maxsum;
    }
};

1.4 被围绕的区域

  1. 题⽬链接:130. 被围绕的区域
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法:
    算法思路:正难则反。
    可以先利⽤ bfs 将与边缘相连的 ‘0’ 区域做上标记,然后重新遍历矩阵,将没有标记过的 ‘0’ 修改成 ‘X’ 即可。
  4. C++代码
class Solution {
    typedef pair<int,int> PII;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int n,m;
    int flag[210][210]={0};
public:
    void bfs(int i,int j,vector<vector<char>>& board)
    {
        queue<PII> q;
        q.push({i,j});
        while(!q.empty())
        {
            auto[a,b]=q.front();
            q.pop();
            for(int k=0;k<4;k++)
            {
                int x=a+dx[k],y=b+dy[k];
                if(x>=0&&x<n&&y>=0&&y<m&&board[x][y]=='O'&&flag[x][y]==0)
                {
                    q.push({x,y});
                    flag[x][y]=1;
                }
            }
        }
    }
    void solve(vector<vector<char>>& board) 
    {
        n=board.size();m=board[0].size();
        for(int j=0;j<m;j++)
        {
            if(board[0][j]=='O'&&flag[0][j]==0)
            {
                flag[0][j]=1;
                bfs(0,j,board);
            }
            if(board[n-1][j]=='O'&&flag[n-1][j]==0)
            {
                flag[n-1][j]=1;
                bfs(n-1,j,board);
            }
        }
        for(int i=0;i<n;i++)
        {
            if(board[i][0]=='O'&&flag[i][0]==0)
            {
                flag[i][0]=1;
                bfs(i,0,board);
            }
            if(board[i][m-1]=='O'&&flag[i][m-1]==0)
            {
                flag[i][m-1]=1;
                bfs(i,m-1,board);
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(board[i][j]=='O'&&flag[i][j]==0)
                board[i][j]='X';
            }
        }
    }
};

二、BFS解决最短路问题

2.1 迷宫中离⼊⼝最近的出⼝

  1. 题⽬链接:1926. 迷宫中离⼊⼝最近的出⼝

  2. 题⽬描述:
    在这里插入图片描述

  3. 解法(bfs 求最短路):
    算法思路:
    利⽤层序遍历来解决迷宫问题,是最经典的做法。
    我们可以从起点开始层序遍历,并且在遍历的过程中记录当前遍历的层数。这样就能在找到出⼝的时候,得到起点到出⼝的最短距离。

  4. C++代码

class Solution {
    int n,m;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int flag[110][110]={0};
    typedef pair<int,int> PII;
    int cnt=0;
public:
    int bfs(int i,int j,vector<vector<char>>& maze)
    {
        queue<PII> q;
        q.push({i,j});
        while(!q.empty())
        {
            cnt++;
            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(x>=0&&x<n&&y>=0&&y<m&&maze[x][y]=='.'&&flag[x][y]==0)
                    {
                        if(x==0||x==n-1||y==0||y==m-1)return cnt;
                        q.push({x,y});
                        flag[x][y]=1;
                    }
                }
            }
        }
        return -1;
    }
    int nearestExit(vector<vector<char>>& maze, vector<int>& entrance) 
    {
        n=maze.size();m=maze[0].size();
        int a=entrance[0],b=entrance[1];
        flag[a][b]=1;
        return bfs(a,b,maze);
    }
};

2.2 最⼩基因变化

  1. 题⽬链接:433. 最⼩基因变化
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法:
    算法思路:
    如果将「每次字符串的变换」抽象成图中的「两个顶点和⼀条边」的话,问题就变成了「边权为 1 的最短路问题」。因此,从起始的字符串开始,来⼀次 bfs 即可。
  4. C++代码
class Solution {
    int ans=0;
    char change[4]={'A','C','G','T'};
public:
    int minMutation(string startGene, string endGene, vector<string>& bank) 
    {
        unordered_set<string> hash(bank.begin(),bank.end());
        unordered_set<string> vis;
        if(!hash.count(endGene))return -1;
        queue<string> q;
        q.push(startGene);
        vis.insert(startGene);
        while(!q.empty())
        {
            ans++;
            int sz=q.size();
            while(sz--)
            {
                string s=q.front();
                q.pop();
                for(int i=0;i<s.size();i++)
                {
                    string tmp=s;
                    for(int ch=0;ch<4;ch++)
                    {
                        tmp[i]=change[ch];
                        if(hash.count(tmp)&&!vis.count(tmp))
                        {
                            if(tmp==endGene)return ans;
                            q.push(tmp);
                            vis.insert(tmp);
                        }
                    }
                }
            }
        }
        return -1;
    }
};

2.3 单词接⻰

  1. 题⽬链接:127. 单词接⻰
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法:和上题一样
  4. C++代码
class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) 
    {
        unordered_set<string> hash(wordList.begin(),wordList.end());
        unordered_set<string> vis;
        if(!hash.count(endWord))return 0;
        queue<string> q;
        q.push(beginWord);
        vis.insert(beginWord);
        int cns=1;
        while(q.size())
        {
            cns++;
            int sz=q.size();
            while(sz--)
            {
                string tmp=q.front();
                q.pop();
                for(int i=0;i<tmp.size();i++)
                {
                    string t=tmp;//换个临时变量是为防止tmp被改变
                    for(int j='a';j<='z';j++)
                    {
                        t[i]=j;
                        if(hash.count(t)&&!vis.count(t))
                        {
                            if(t==endWord)return cns;
                            q.push(t);
                            vis.insert(t);
                        }
                    }
                }
            }
        }
        return 0;
    }
};

2.4 为⾼尔夫⽐赛砍树

  1. 题⽬链接:675. 为⾼尔夫⽐赛砍树
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法:
    算法思路:
    a. 先找出砍树的顺序;
    b. 然后按照砍树的顺序,⼀个⼀个的⽤ bfs 求出最短路即可。
  4. C++代码
class Solution {
    int n,m;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int ans=0;
    int vis[55][55]={0};
public:
    int bfs(int bx,int by,int ex,int ey,vector<vector<int>>& forest)
    {
        if(bx==ex&&by==ey)return 0;
        queue<pair<int,int>> q;
        q.push({bx,by});
        vis[bx][by]=1;
        memset(vis,0,sizeof(vis));//这里一定要清空之前的数据
        int cnt=0;
        while(!q.empty())
        {
            cnt++;
            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(x>=0&&x<n&&y>=0&&y<m&&forest[x][y]&&!vis[x][y])
                    {
                        if(x==ex&&y==ey)return cnt;
                        q.push({x,y});
                        vis[x][y]=1;
                    }
                }
            }
        }
        return -1;
    }
    int cutOffTree(vector<vector<int>>& forest) 
    {
        n=forest.size();m=forest[0].size();
        //先找到要砍的树的顺序
        vector<pair<int,int>> v;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(forest[i][j]>1)v.push_back({i,j});
            }
        }
        sort(v.begin(),v.end(),[&](const pair<int,int>&t1,const pair<int,int>&t2){
            return forest[t1.first][t1.second]<forest[t2.first][t2.second];
        });
        int bx=0,by=0;
        for(auto&[a,b]:v)
        {
            int ret=bfs(bx,by,a,b,forest);
            if(ret==-1)return -1;
            ans+=ret;
            bx=a;by=b;
        }
        return ans;
    }
};

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

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

相关文章

Linux高级编程_31_消息队列

文章目录 消息队列作用&#xff1a;特点&#xff1a;消息队列限制值&#xff1a;注意&#xff1a;命令&#xff1a;ftok函数作用&#xff1a;语法&#xff1a; msgget函数作用&#xff1a;语法&#xff1a; msgsnd函数作用&#xff1a;语法&#xff1a; msgrcv函数作用&#xf…

QT实现QInputDialog中文按钮

这是我记录Qt学习过程心得文章的第三篇&#xff0c;主要是为了方便QInputDialog输入框的使用&#xff0c;通过自定义的方式&#xff0c;按钮中文化&#xff0c;统一封装成一个函数&#xff0c;还是写在了Skysonya类里面。 实现代码&#xff1a; //中文按钮文本输入对话框 QSt…

【gRPC】1—gRPC是什么

gRPC是什么 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star~&#x1f60a; &#x1f4d6;RPC专栏&#xff1a;https://b…

鸿蒙--播放器状态控制

各个页面共享同一个播放状态&#xff0c;而且可以互相控制&#xff0c;如果传递来传递去会非常的麻烦&#xff0c;但是他们都是Tabs组件内的&#xff0c;我们在index页面提供一个状态&#xff0c;在各个组件接收即可 创建两个子组件&#xff0c;一个是播放控制的子组件&#xf…

1. Oracle 安装报错——环境变量过长

文章目录 1. 报错详细信息2. 解决方案2.1 方案一&#xff1a;修改配置文件cvu_prereq.xml2.2 方案二&#xff1a;修改环境变量配置 1. 报错详细信息 安装 Oracle 过程中&#xff0c;在执行 “先决条件检查” 时报错&#xff1a; 报错内容&#xff1a; This test checks wheth…

【自然语言处理】(3) --RNN循环神经网络

文章目录 RNN循环神经网络一、传统神经网络的问题二、RNN的基本结构三、计算过程4. RNN的局限 总结 RNN循环神经网络 循环神经网络&#xff08;RNN&#xff0c;Recurrent Neural Network&#xff09;是一种用于处理序列数据的神经网络模型。其关键特性在于网络节点&#xff08…

现代数字信号处理I-P2概率论学习笔记

目录 学习视频链接&#xff1a; 1. 三要素及关系 2. 期望和方差的定义及基本性质 2.1 期望&#xff08;均值&#xff09;定义&#xff1a; 在实际工作中很难获得随机变量的分布或者概率密度&#xff0c;用矩描述随机变量 2.2 期望基本性质&#xff1a; 2.3 方差定义 2.…

Android Studio Koala Feature Drop 稳定版现已推出

作者 / Android Studio 产品经理 Sandhya Mohan Android Studio Koala Feature Drop (2024.1.2) 现已推出&#xff01;&#x1f428; &#x1f517; Android Studio https://developer.android.google.cn/studio 今年早些时候&#xff0c;我们宣布每个 Android Studio 动物版本…

10月9日笔记(域内用户登录凭据窃取)

缺&#xff1a;BloodHound自动化分析域环境未实现&#xff08;环境问题&#xff09; 获取常见应用软件凭据 为了扩大可访问的范围&#xff0c;测试人员通常会搜索各种常见的密码存储位置&#xff0c;以获取用户凭据。一些特定的应用程序可以存储密码&#xff0c;以方便用户管…

python的特殊方法——魔术方法

前言 __init__(self[]) ​编辑 __call__(self [, ...]) __getitem__(self, key) __len__(self) __repr__(self) / __str__(self) __add__(self, other) __radd__(self, other) 参考文献 前言 官方定义好的&#xff0c;以两个下划线开头且以两个下划线结尾来命名的方法…

PostgreSQL学习笔记四:GUI管理工具

PostgreSQL 是一款广泛使用的开源关系数据库管理系统&#xff0c;拥有许多图形用户界面&#xff08;GUI&#xff09;工具来帮助用户更高效地管理数据库。以下是一些流行的 PostgreSQL 管理工具&#xff1a; pgAdmin&#xff1a; 一个流行的开源 PostgreSQL GUI 工具&#xff0c…

处理“navicat premium 2003 - 无法在 192.168.10.140 上连接到 MySQL 服务器(10060“未知错误“)”的问题:

以下是一些可能的解决方法来处理“navicat premium 2003 - 无法在 192.168.10.140 上连接到 MySQL 服务器&#xff08;10060"未知错误"&#xff09;”的问题&#xff1a; **一、检查 MySQL 服务状态** 1. 确认 MySQL 服务是否正在运行。你可以在服务器上通过任务管…

Django makemigrations时出现TypeError: ‘module‘ object is not iterable

使用Python 3.11、Django 5.1.2 写完model进行makemigrations时出现报错 报错的最下面提到了我自己创建的一个应用里的urls.py&#xff0c;尝试着给里面加上一个列表 然后问题解决了。。。 不知道为什么 makemigrations的时候会去检查urls。。。

mybatisPlus对于pgSQL中UUID和UUID[]类型的交互

在PGSQL中&#xff0c;有的类型是UUID和UUID[]这种类型&#xff0c;在mybatis和这些类型交互的时候需要手动设置类型处理器才可以&#xff0c;这里记录一下类型处理器的设置 /*** UUID类型处理器*/ public class UUIDTypeHandler extends BaseTypeHandler<UUID> {/*** 获…

Kubernetes中的pod管理及优化

华子目录 什么是pod1.创建自主式pod&#xff08;生产不推荐&#xff09;优点缺点示例1示例2示例3示例4 2.利用控制器管理pod&#xff08;推荐&#xff09;应用版本的更新 3.利用yaml文件部署应用优点3.1yaml配置文件参数3.2如何获取资源帮助 yaml文件编写示例1.运行简单的单个容…

实现std::sort,replace,fill,accumulate,equal等函数

std::sort /// <summary>/// std::sort 是从小到大排列的/// </summary>/// <typeparam name"IteratorClass"></typeparam>/// <typeparam name"ComparingFunctions"></typeparam>/// <param name"itBegin&qu…

PAT甲级-1150 Travelling Salesman Problem

题目 题目大意 旅行商问题是NP-hard问题&#xff0c;即没有多项式时间内的解法&#xff0c;但是可以验证答案是否正确。给定一个无向图&#xff0c;判断简单环&#xff0c;复杂环和非环。对应“TS simple cycle”、“TS cycle”、“Not a TS cycle”。还要求出环的最小路径权值…

力扣11-盛最多水的容器

题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾斜容器。…

DAY28||39.组合总数 |40.组合总和Ⅱ |131.分割回文串

39.组合总数 题目&#xff1a;39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以…

Java基本数据类型转换

一、自动类型转换 1.基本介绍 当Java程序在进行赋值或者运算时&#xff0c;精度小的类型自动转换为精度大的数据类型&#xff0c;这个就是自动类型转换数据类型按精度&#xff08;容量&#xff09;大小进行排序为&#xff1a; ![在这里插入图片描述](https://i-blog.csdnimg.…