Flood fill算法:从一个起点开始,然后每一次随机选一个新加入的格子看周围能不能扩展新的格子,如果能的话就把他扩展进来,直到不能扩展新的格子为止。
需要判重,同样一个格子只能覆盖一次
可以在线性时间复杂度内,找到某个点所在的连通块(找连通块)
宽搜和深搜都可以实现,深搜可能发生爆栈
总结:
先找到进入floodfill的条件
然后加入把起点加入队列并进行标记
只要队列不空就对格子进行扩展(要除去自己因为自己已经被覆盖过了)
然后判定是否有效(是否超出范围,是否已经覆盖或者是石头)
把扩展的点加入队列并进行标记
然后从已经加入的队列里的数随机选一个再次进行扩展
#include<iostream>
#include<string>
#include<algorithm>
#define x first
#define y second
using namespace std;
const int N=1010,M=N*N;
typedef pair<int,int>PII;//要存坐标
char g[N][N];
PII q[M];//队列
bool st[N][N];//宽搜基本要判重
int n,m,cnt;
void bfs(int sx,int sy)
{
int hh=0,tt=0;//模拟队列
q[0]={sx,sy};
st[sx][sy]=true;//已经覆盖了并且保证时间复杂度是线性
while(hh<=tt)
{
PII t=q[hh++];
for(int i=t.x-1;i<=t.x+1;i++)//遍历格子的周围
for(int j=t.y-1;j<=t.y+1;j++)
{
if(i==t.x&&j==t.y) continue;//把中间的挖掉
if(i<0||i>=n||j<0||j>=m) continue;//越界不行
if(g[i][j]=='.'||st[i][j]) continue;//是石头不行或者说已经覆盖
q[++tt]={i,j};
st[i][j]=true;
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>g[i];
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(g[i][j]=='W'&&!st[i][j])//进入floodfill的条件
{
bfs(i,j);
cnt++;
}
cout<<cnt;
}