Flood Fill模型
1097. 池塘计数
简单分析:
模板题
统计有几个连接的池塘,本质上的flood fill就是用dfs或bfs去搜索,搜索到了就把是否访问标签设置为true,
如果仍有没访问的点,则对这个点继续做一次dfs或bfs
八个方向,可以用一个小trick:dx=[-1, -1, 0, 1, 1, 1, 0, -1], dy=[0, 1, 1, 1, 0, -1, -1, -1] (上,右上,左,左下..顺时针)
#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second
using namespace std;
const int N = 1010;
typedef pair<int, int> PII;
int n , m;
char ch[N][N];
bool st[N][N];
PII q[N * N];
void bfs(int sx, int sy){
int hh = 0, tt = -1;
q[++ tt] = {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(st[i][j] || ch[i][j] == '.') continue;
q[++ tt] = {i, j};
st[i][j] = true;
}
}
}
}
int main()
{
cin >> n >> m;
int cnt = 0;
for(int i = 0; i < n ; i ++){
scanf("%s", ch[i]);
}
for(int i = 0 ;i < n ; i ++){
for(int j = 0 ; j < m ; j++){
if(ch[i][j] == 'W' && !st[i][j]){
bfs(i, j);
cnt ++;
}
}
}
cout << cnt;
return 0;
}
python3写法:
from collections import deque
if __name__ == "__main__":
n, m = map(int, input().split())
st = [[False] * m for _ in range(n)]
mapp = []
cnt = 0
dx, dy = [-1, -1, 0, 1, 1, 1, 0, -1], [0, 1, 1, 1, 0, -1, -1, -1]
# def dfs(x: int, y: int) -> None:
# '''dfs在这道题会爆栈'''
# st[x][y] = True
# for i in range(8):
# nx, ny = x + dx[i], y + dy[i]
# if nx < 0 or nx >= n or ny < 0 or ny >= m:
# continue
# if st[nx][ny]:
# continue
# if mapp[nx][ny] == 'W':
# dfs(nx, ny)
def bfs(x: int, y: int) -> None:
q = deque([(x, y)])
st[x][y] = True
while q:
t = q.popleft()
for i in range(8):
nx, ny = t[0] + dx[i], t[1] + dy[i]
if nx < 0 or nx >= n or ny < 0 or ny >= m:
continue
if st[nx][ny]:
continue
if mapp[nx][ny] == 'W':
st[nx][ny] = True
q.append((nx, ny))
for _ in range(n):
mapp.append(input())
for i in range(n):
for j in range(m):
if mapp[i][j] == 'W' and st[i][j] == False:
bfs(i, j)
cnt += 1
print(cnt)
1098. 城堡问题
简单分析:
'''
在flood fill模板上稍微复杂了一下
现在我们需要思考什么时候可以向上下左右四个方向去走?
1. 没有被墙挡住
对于每一个位置,用一个数p(0-15)来表示,可以转化成2进制数,1111从左往右分别表示是否有南、东、北、西墙,
p >> i & 1 可以来判断是否存在i墙(i表示墙索引,从西开始反着编号)
2. 还没有访问过
'''
c++代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 55;
int m, n;
int g[N][N];
bool st[N][N];
PII q[N * N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; // 分别是上右下左
int bfs(int sx, int sy){
st[sx][sy] = true;
int hh = 0, tt = -1;
q[ ++ tt] = {sx, sy};
while( hh <= tt ){
PII t = q[hh ++];
// 下述过程建议优化一下,这是我初版的思路,没优化,其实可以合并起来,参照python代码
if(t.x + dx[0] >= 0 && t.x + dx[0] < m && t.y + dy[0] >= 0 && t.y + dy[0] < n && !st[t.x + dx[0]][t.y + dy[0]] && !(g[t.x + dx[0]][t.y + dy[0]] >> 3 & 1)){
q[++ tt] = {t.x + dx[0], t.y + dy[0]};
st[t.x + dx[0]][t.y + dy[0]] = true;
}
if(t.x + dx[1] >= 0 && t.x + dx[1] < m && t.y + dy[1] >= 0 && t.y + dy[1] < n && !st[t.x + dx[1]][t.y + dy[1]] && !(g[t.x + dx[1]][t.y + dy[1]] & 1)){
q[++ tt] = {t.x + dx[1], t.y + dy[1]};
st[t.x + dx[1]][t.y + dy[1]] = true;
}
if(t.x + dx[2] >= 0 && t.x + dx[2] < m && t.y + dy[2] >= 0 && t.y + dy[2] < n &&!st[t.x + dx[2]][t.y + dy[2]] && !(g[t.x + dx[2]][t.y + dy[2]] >> 1 & 1)){
q[++ tt] = {t.x + dx[2], t.y + dy[2]};
st[t.x + dx[2]][t.y + dy[2]] = true;
}
if(t.x + dx[3] >= 0 && t.x + dx[3] < m && t.y + dy[3] >= 0 && t.y + dy[3] < n &&!st[t.x + dx[3]][t.y + dy[3]] && !(g[t.x + dx[3]][t.y + dy[3]] >> 2 & 1)){
q[++ tt] = {t.x + dx[3], t.y + dy[3]};
st[t.x + dx[3]][t.y + dy[3]] = true;
}
}
return tt + 1;
}
/*
对于墙壁的情况分别有:(1,西墙)(2,北墙)(4,东墙)(8,南墙)(3 西北墙)(5,西东墙)(6,东北墙)
(7,西北东墙)(9,西南墙)(10,北南墙)(11, 西北男墙)(12,东南墙)(13,西东南墙)(14,北东南墙)
(15,西北东南墙)
1.首先读入所有的数字信息,
2.需要定义每一个空间是否已经访问
3.从1,1空间开始访问,用bfs向外边扩散,分别去看上下左右的空间,如果上边没有南墙则访问(g[i][j] >> 3 & 1),
如果下边没有北墙可以访问(g[i][j] >> 1 & 1)
如果左边没有东墙可以访问(g[i][j] >> 2 & 1)
如果右边没有西墙可以访问。(g[i][j] & 1)
*/
int main()
{
int cnt = 0;
int res = 0;
cin >> m >> n;
for(int i = 0; i < m ; i++){
for(int j = 0 ; j < n; j ++){
cin >> g[i][j];
}
}
for(int i = 0 ; i < m; i ++){
for(int j = 0; j < n ; j++){
if(!st[i][j]){
int s = bfs(i, j);
if(s > res){
res = s;
}
cnt ++;
}
}
}
cout << cnt << endl;
cout << res;
return 0;
}
python3代码:
from collections import deque
if __name__ == "__main__":
m, n = map(int, input().split())
mapp = [ list(map(int, input().split())) for _ in range(m)]
st = [[False] * n for _ in range(m)]
cnt, max_size = 0, 0
dx, dy = [0, -1, 0, 1], [-1, 0, 1, 0]
def bfs(x: int, y: int) -> int:
q = deque([(x, y)])
st[x][y] = True
size = 0
while q:
tx, ty = q.popleft()
size += 1
for i in range(4):
nx, ny = tx + dx[i], ty + dy[i]
if nx < 0 or nx >= m or ny < 0 or ny >= n:
continue
if st[nx][ny]:
continue
if mapp[tx][ty] >> i & 1 == 0:
st[nx][ny] = True
q.append((nx, ny))
return size
for i in range(m):
for j in range(n):
if not st[i][j]:
max_size = max(bfs(i, j), max_size)
cnt += 1
print(cnt)
print(max_size)