BFS:Floodfill算法
创始人
2025-01-11 13:06:26
0

Floodfill,翻译为洪水灌溉,而floodfill算法本质上是为了解决在矩阵中性质相同的联通块问题。

 一、图像渲染

. - 力扣(LeetCode)

        与dfs一样,从指定的起点开始向四个方向扩展,区别就是用之前通过参数将下标关系传递给dfs,而现在是将下标关系的键值对传给queue。

class Solution { public:  //定义4个方向     int dx[4]={0,0,1,-1};     int dy[4]={1,-1,0,0};     typedef pair PII;     vector> floodFill(vector>& image, int sr, int sc, int color)      {       //采用BFS算法解决floodfill算法,  解决相同性质的矩阵联通块问题        int prev=image[sr][sc];        if(prev==color) return image;        int m=image.size(),n=image[0].size();        queue q;//队列        q.emplace(sr,sc);        while(!q.empty())        {          //先修改当前位置          auto [a,b]=q.front();//c++14的玩法          q.pop();          image[a][b]=color;//修改成color          for(int k=0;k<4;++k)           {             int x=dx[k]+a,y=dy[k]+b;             if(x>=0&&x=0&&y

 二、岛屿数量

. - 力扣(LeetCode)

 

  1.  因为要计算岛屿的数量,所以我们每进行一次bfs就要统计一下该岛屿,因为我们可以将bfs单独封装成一个函数。

  2.在扩展的时候,我们需要标记我们扩展过的网格,这里有两种方案:

(1)修改值,但是修改值会改变原数据,必须要想办法修改回来。

(2)标记数组(常用),相同大小的标记数组,将探索过的网格标记为true

class Solution { public:     int dx[4]={1,-1,0,0};     int dy[4]={0,0,1,-1};     typedef pair PII;     int m,n;//因为要单独封装一个BFS     bool check[301][301];//标记数组 看看哪些点是选过的      int numIslands(vector>& grid) {         //ret统计一共有多少个联通块         int ret=0;         //直接修改原数组的话 可能会有问题         m=grid.size();         n=grid[0].size();         for(int i=0;i>& grid,int i,int j)     {         queue q;//队列统计下标实现BFS         q.emplace(i,j);         check[i][j]=true;         while(!q.empty())         {             auto [a,b]=q.front();             q.pop();             for(int k=0;k<4;++k)             {                 int x=dx[k]+a,y=dy[k]+b;                 if(x>=0&&x=0&&y

三、岛屿的最大面积

. - 力扣(LeetCode)

         我们需要统计每个岛屿的大小,所以我们可以将bfs单独封装成一个函数,然后利用他的返回值返回岛屿的大小,在主函数中去更新找到最大值。 

class Solution { public:     int dx[4]={1,-1,0,0};     int dy[4]={0,0,1,-1};     typedef pair PII;     int m,n;//因为要单独封装一个BFS     bool check[50][50];//标记数组 看看哪些点是选过的     int maxAreaOfIsland(vector>& grid)      {         int ret=0;//统计最大岛屿数量         m=grid.size(),n=grid[0].size();         for(int i=0;i>& grid,int i,int j)     {         queue q;         q.emplace(i,j);         check[i][j]=true;         int count=1;         while(!q.empty())         {             auto [a,b]=q.front();             q.pop();             for(int k=0;k<4;++k)             {                 int x=dx[k]+a,y=dy[k]+b;                 if(x>=0&&x=0&&y

 四、被围绕的区域

. - 力扣(LeetCode)

        如果直接做的话,我们会发现如果我们处理一个区域的时候一旦触碰到边界,那么就全部需要回头。或者说得先遍历一遍,确认这个联通块没有触碰边界,然后再遍历一次去标记,这样显然效率是很低的。因此我们的解决方案就是正难则反。 

(1)先从边界走一波bfs,将O全部修改成 .

(2)然后遍历矩阵(遍历矩阵的时候可以顺便还原,所以这个地方我们就不需要设置标记数组),将剩下的O修改成X,然后将.还原成O。

class Solution { public:     const int dx[4]={1,-1,0,0};     const int dy[4]={0,0,1,-1};     typedef pair PII;     int m,n;//因为要单独封装一个BFS     void solve(vector>& board) {       m=board.size(),n=board[0].size();       //先处理第一行和最后一行       for(int j=0;j>& board,int i,int j)     {         queue q;         q.emplace(i,j);         board[i][j]='.';         while(!q.empty())         {             auto [a,b]=q.front();             q.pop();             for(int k=0;k<4;++k)              {                 int x=dx[k]+a,y=dy[k]+b;                 if(x>=0&&x=0&&y

五、太平洋大西洋水流问题

. - 力扣(LeetCode)

        如果我们直接做的话,显然需要需要遍历矩阵,然后每遍历一个点就要判断该点是否可以同时流向太平洋和大西洋,显然这样是十分麻烦的。因此我们的思路就是正难则反。

 (1)从矩阵的边界开始逆推(从低往高处流)

(2)用两个标记数组进行标记,一个标记表示可以流向太平洋,另一个标记可以流向大西洋,最后我们将两个标记数组都标记过的坐标进行统计并返回即可。

class Solution { public:     const int dx[4]={0,0,-1,1};     const int dy[4]={1,-1,0,0};     int m,n;     vector> pacificAtlantic(vector>& h)      {        //正难则反  用两个标记数组,用边界去往中间走,将能走的位置给标记了        //最后两个标记数组都被标记的地方就是我们最终的结果        m=h.size(),n=h[0].size();        //定义两个标记数组        vector> atl(m,vector(n));        auto pac=atl;        //先探索行        for(int i=0;i> ret;        for(int i=0;i>& h,int i,int j,vector>&vis)     {         queue> q;         q.emplace(i,j);         vis[i][j]=true;         while(!q.empty())         {             auto [a,b]=q.front();             q.pop();             for(int k=0;k<4;++k)              {                 int x=dx[k]+a,y=dy[k]+b;                 if(x>=0&&x=0&&y=h[a][b]&&vis[x][y]==false)                   {                     q.emplace(x,y);                     vis[x][y]=true;                   }              }         }     } };

 六、扫雷游戏(重点)

. - 力扣(LeetCode)

         这题用dfs不需要标记数组,而用bfs需要用到标记数组,因为深度优先会将一个方格能扩展的都给扩展了,此时都在数组中会进行修改,但是广度优先是先把要扩展的全都丢进队列,然后再一个个处理,所以bfs需要一个标记数组来帮助我们。 

class Solution { public:     int dx[8]={0,0,1,-1,1,1,-1,-1};     int dy[8]={1,-1,0,0,1,-1,1,-1}; //周围的八个方向     int m,n;     vector> updateBoard(vector>& board, vector& click) {        m=board.size(),n=board[0].size();        int x=click[0],y=click[1];        if(board[x][y]=='M') board[x][y]='X';        else bfs(board,x,y);//不是雷,就向外扩展        return board;     }     void bfs(vector>& board,int i,int j)     {       queue> q;       vector> vis(m,vector(n));//标记数组       q.emplace(i,j);       vis[i][j]=true;       while(!q.empty())       {         auto[a,b]=q.front();         q.pop();         int count=0;//数雷         for(int k=0;k<8;++k)         {             int x=dx[k]+a,y=dy[k]+b;             if(x>=0&&x=0&&y=0&&x=0&&y

七、衣柜整理

. - 力扣(LeetCode)

class Solution { public:     const int dx[2]={1,0};     const int dy[2]={0,1};     bool vis[100][100];     int m,n,cnt;     int wardrobeFinishing(int _m, int _n, int _cnt) {         m=_m,n=_n,cnt=_cnt;         int ret=0;//统计需要整理的格子         queue> q;         q.emplace(0,0);         vis[0][0]=true;         while(!q.empty())         {             auto[a,b]=q.front();             q.pop();             ++ret;             for(int k=0;k<2;++k)             {                 int x=dx[k]+a,y=dy[k]+b;                 if(x

 

相关内容

热门资讯

据统计!wepoker手机版辅... 据统计!wepoker手机版辅助,新超圣辅助靠谱不,积累教程(今日头条)新超圣辅助靠谱不是不是有人用...
五分钟辅助!掌中乐辅助(辅助挂... 五分钟辅助!掌中乐辅助(辅助挂)果然是真的辅助神器(确实有挂)1、玩家可以在掌中乐辅助透视最简单三个...
现场直击!wpk透视辅助靠谱吗... 现场直击!wpk透视辅助靠谱吗,微信小程序哥哥打大a辅助器,手段教程(果真有挂)1、微信小程序哥哥打...
第二分钟辅助!新星游辅助软件试... 第二分钟辅助!新星游辅助软件试用版(辅助挂)都是真的是有辅助app(有挂教程)新星游辅助软件试用版破...
据悉!wpk俱乐部辅助器,广西... 据悉!wpk俱乐部辅助器,广西老友修改器,策略教程(今日头条)1、打开软件启动之后找到中间准星的标志...
第3分钟辅助!微信闲来辅助神器... 第3分钟辅助!微信闲来辅助神器app(辅助挂)本来真的是有辅助插件(有挂头条)1、起透看视 微信闲来...
2026版总结!wpk透视插件... 2026版总结!wpk透视插件,老k麻将辅助器,方式教程(有挂规律)1、全新机制【老k麻将辅助器ai...
教学辅助挂!菠萝辅助器免费版的... 教学辅助挂!菠萝辅助器免费版的特点,赣牌圈插件,积累教程(有挂解惑)1、赣牌圈插件透视辅助软件激活码...
4分钟辅助!浙江游戏茶苑脚本修... 4分钟辅助!浙江游戏茶苑脚本修改(辅助挂)其实存在有辅助工具(果真有挂)1、上手简单,内置详细流程视...
第六分钟辅助!斗城麻将微信有没... 第六分钟辅助!斗城麻将微信有没有挂(辅助挂)一贯存在有辅助方法(发现有挂)运斗城麻将微信有没有挂辅助...