[算法:BFS]Flood Fill模型

Posted Lazy@慵懒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[算法:BFS]Flood Fill模型相关的知识,希望对你有一定的参考价值。

池塘计数

农夫约翰有一片 N∗M 的矩形土地。最近,由于降雨的原因,部分土地被水淹没了。
现在用一个字符矩阵来表示他的土地。
每个单元格内,如果包含雨水,则用”W”表示,如果不含雨水,则用”.”表示。
现在,约翰想知道他的土地中形成了多少片池塘。
每组相连的积水单元格集合可以看作是一片池塘。
每个单元格视为与其上、下、左、右、左上、右上、左下、右下八个邻近单元格相连。
请你输出共有多少片池塘,即矩阵中共有多少片相连的”W”块。
输入格式
第一行包含两个整数 N 和 M。
接下来 N 行,每行包含 M 个字符,字符为”W”或”.”,用以表示矩形土地的积水状况,字符之间没有空格。
输出格式
输出一个整数,表示池塘数目。
数据范围
1≤N,M≤1000
输入样例:

输出样例:
3

思路:

我们可以采用双重循环进行判断,当找到一个有水的地方,以此为中心,进行搜索与之相连有水的地方,遍历完毕之后,即可得到结果

代码及其解析

#include<iostream>
#include<cstring>

using namespace std;

//将N,M设置为常量
const int N=1010;
const int M=1010;
// vec表示矩形土地,visited 表示是否遍历过次坐标
char vec[N][M];
int visited[N][M];
// 我们要遍历的方向  上、下、左、右、左上、右上、左下、右下
int dir[8][2]=-1,0,1,0,0,-1,0,1,-1,-1,-1,1,1,-1,1,1;
//队列,我们采用数组进行模拟,比queue库种的容器,效率高
pair<int,int> que[N*M];
// i,j表示水的当前坐标;n,m表示土地的行和列
void bfs(int i,int j,const int n,const int m)
    //当前队列坐标
    int idx=0;
    //队列长度
    int len=0;
    //将当前坐标放入队列,进行标记
    que[0]=i,j;
    visited[i][j]=1;
    //队列里面的元素不为空时,未搜索完毕
    while( idx <= len)
    // 取出队列头部的元素
        pair<int,int> tmp=que[idx++];
        int row=tmp.first;
        int col=tmp.second;
   // 进行八个方向的扩展
       for(int i=0;i<8;i++)
        int x=row+dir[i][0];
        int y=col+dir[i][1];
        if(x<0||x>=n||y<0||y>=m||visited[x][y]||vec[x][y]!='W')
            continue;
        
    //满足要求的坐标,放入队列 ;len表示长度也表示队尾的坐标位置
        que[++len]=x,y;
        visited[x][y]=1;
       
    
    
    return ;

int main()
    //数组初始化
    memset(vec,0,sizeof vec);
    memset(visited,0,sizeof visited);
    //输入数据
    int n=0,m=0;
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            cin>>vec[i][j];
        
    
    // ret表示最终结果既有多少块池塘
    int ret=0;
    //for循环遍历
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
             //找到有谁的地方,并且此坐标之前没有遍历过
            if(vec[i][j]=='W'&&visited[i][j]==0)
                ret++;
                //以此位中心进行广度搜索
                bfs(i,j,n,m);
            
        
    
    //输出结果
    cout<<ret<<endl;
    return 0;
    

题目链接:

https://www.acwing.com/problem/content/1099/

城堡问题


图1是一个城堡的地形图。
请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。
城堡被分割成 m∗n个方格区域,每个方格区域可以有0~4面墙。
注意:墙体厚度忽略不计。
输入格式
第一行包含两个整数 m 和 n,分别表示城堡南北方向的长度和东西方向的长度。
接下来 m 行,每行包含 n 个整数,每个整数都表示平面图对应位置的方块的墙的特征。

每个方块中墙的特征由数字 P 来描述,我们用1表示西墙,2表示北墙,4表示东墙,8表示南墙,P 为该方块包含墙的数字之和。

例如,如果一个方块的 P 为3,则 3 = 1 + 2,该方块包含西墙和北墙。

城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙。

输入的数据保证城堡至少有两个房间。

输出格式
共两行,第一行输出房间总数,第二行输出最大房间的面积(方块数)。

数据范围
1≤m,n≤50,
0≤P≤15
输入样例:
4 7
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13
输出样例:
5
9

代码及其解析:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
//根据题目设置N,M常量值
const int N=51;
const int M=51;
//vec存储输入数据,visited表示vec对应位置是否被遍历过
int vec[N][M];
int visited[N][M];
// 题目结果 Maxarea表示最大房间的面积 ,Count表示房间数目
int Maxarea=0;
int Count=0;
//队列
pair<int ,int> que[N*M];
//dir移动方向  wall1表示墙体数组
int dir[4][2]=0,-1,-1,0,0,1,1,0;
int wall1[4]=1,2,4,8;

//row col表示坐标   ;  n和m 城堡南北方向的长度和东西方向的长度。
void bfs(int row,int col,const int n,const int m)
    int idx=0;
    int len=0;
    que[0]=row,col;
    visited[row][col]=1;
    int area=1;
    
    while(idx<=len)
     //  取出队列当中的数据,进行搜索
        pair<int ,int>  tmp=que[idx++];
        for(int i=0;i<4;i++)
            int x=tmp.first+dir[i][0];
            int y=tmp.second+dir[i][1];
            if(x<0||x>=n||y<0||y>=m)
                continue;
            
            if(visited[x][y])
                continue;
            
            //当前vec数组数据&墙体数组等于1,表示有墙
            if((vec[tmp.first][tmp.second]&wall1[i]))
                continue;
            
            //将坐标放入队列,进行标记
            que[++len]=x,y;
            visited[x][y]=1;
            area++;
        
    
    //遍历完毕之后,判断是否是最大的房间面积
    Maxarea=max(Maxarea,area);


int main()
     //初始化
    memset(vec,0,sizeof vec);
    memset(visited,0,sizeof visited);
    //输入数据
    int n=0,m=0;
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            cin>>vec[i][j];
        
    
    //for循环遍历,进行搜索
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            if(visited[i][j]==0)
                bfs(i,j,n,m);
                Count++;
            
        
    
    //输出结果
    cout<<Count<<endl;
    cout<<Maxarea<<endl;
    return 0;


题目链接

https://www.acwing.com/problem/content/1100/

本片文章参考

  • AcWing网站
    如有侵权,请联系删除

以上是关于[算法:BFS]Flood Fill模型的主要内容,如果未能解决你的问题,请参考以下文章

1097. 池塘计数Flood Fill 搜索

洪水覆盖算法(Flood Fill):颜色填充

LeetCode算法题-Flood Fill(Java实现)

图像处理------泛洪填充算法(Flood Fill Algorithm) 油漆桶功能

CF 1114 D. Flood Fill

LeetCode - Flood Fill