引入
Flood Fill应用的题型主要在于求连通块的题目;
例题
池塘计数
题面
题意
问有多少个相连的’W’块,从样例不难看出,一共三个连通块;
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <utility>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
int n,m,ans;
char G[N][N];
bool vis[N][N];
int dx[9] = {0,0,0,1,-1,-1,-1,1,1};
int dy[9] = {0,1,-1,0,0,1,-1,1,-1};
typedef pair<int,int> pii;
queue<pii> que;
void bfs(int x,int y){
que.push({x,y});
++ans;
while(!que.empty()){
auto u = que.front();
que.pop();
if(vis[u.first][u.second]) continue;
vis[u.first][u.second] = 1;
for(int i=1,xx,yy;i<=8;++i){
xx = u.first + dx[i];
yy = u.second + dy[i];
if(G[xx][yy] == 'W' && !vis[xx][yy]){
que.push({xx,yy});
}
}
}
}
void solve(){
cin >> n >> m;
for(int i=1;i<=n;++i){
cin >> (G[i] + 1);
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(G[i][j] == 'W' && !vis[i][j]){
bfs(i,j);
}
}
}
cout << ans << '\n';
}
int main(){
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
solve();
return 0;
}
城堡问题
题面
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <utility>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 1e2 + 10;
int G[N][N];
int n,m;
bool vis[N][N];
int area,ans;
typedef pair<int,int> pii;
queue<pii> que;
int dx[4] = {0,-1,0,1};
int dy[4] = {-1,0,1,0};
void bfs(int x,int y){
++ans;
que.push({x,y});
int _area = 0;
while(!que.empty()){
auto u = que.front();
que.pop();
if(vis[u.first][u.second]) continue;
++_area;
vis[u.first][u.second] = 1;
for(int i=0,xx,yy;i<4;++i){
xx = u.first + dx[i];
yy = u.second + dy[i];
if(xx < 1 || xx > n || yy < 1 || yy > m) continue;
if(vis[xx][yy]) continue;
//城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙
//只需要判断一边有无墙即可
//看看第i+1位是否为1
if((G[u.first][u.second]>>i) & 1) continue;
que.push({xx,yy});
}
}
area = max(area,_area);
}
void solve(){
cin >> n >> m;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
cin >> G[i][j];
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(!vis[i][j]) bfs(i,j);
}
}
cout << ans << '\n';
cout << area << '\n';
}
int main(){
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
solve();
return 0;
}
山峰与山谷
题面
Code
#include <iostream>
#include <cstdio>
#include <utility>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
int dx[] = {0,0,1,-1,-1,1,-1,1};
int dy[] = {1,-1,0,0,1,1,-1,-1};
typedef pair<int,int> pii;
queue<pii> que;
int n;
bool vis[N][N];
int h[N][N];
//是否还有区域比这块区域更低(高)
void bfs(int x,int y,bool & highest,bool & lowest){
que.push({x,y});
while(!que.empty()){
auto u = que.front();
que.pop();
if(vis[u.first][u.second]) continue;
vis[u.first][u.second] = 1;
for(int i=0,xx,yy;i<8;++i){
xx = u.first + dx[i];
yy = u.second + dy[i];
if(xx > n || yy > n || xx < 1 || yy < 1) continue;
if (h[xx][yy] != h[u.first][u.second]){
//有地方比当前高 那么当前就不是最高的
if (h[xx][yy] > h[u.first][u.second]) highest = 0;
//有比我们低的,我们就不是最低的
else lowest = 0;
}
else{
if (!vis[xx][yy]){
que.push({xx,yy});
}
}
}
}
}
void solve(){
cin >> n;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
cin >> h[i][j];
int ans1 = 0,ans2 = 0;//山峰和山谷
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(!vis[i][j]){
bool lowest = 1,highest = 1;
bfs(i,j,highest,lowest);
if(lowest) ++ans2;
if(highest) ++ans1;
}
}
}
cout << ans1 << ' ' << ans2 << '\n';
}
int main(){
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
solve();
return 0;
}