[算法: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模型的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode算法题-Flood Fill(Java实现)