D题:Grid and Magnet
标签:搜索
题意:给定一个
n
n
nx
m
m
m的地图,地图中 # 表示不可以走,. 表示可以走。在此基础上加上一个限制,如果一个 . 周围上下左右中有一个位置有 #,就不能移动。求从 . 的地方走最多能到达的格子数。
题解:如果没有限制,就是普通的搜索了,暴力跑就好了。加上这个限制,如果我们像连通块一样,提前把某个格子跑到,并且因为 周围上下左右有一个#就不能移动,提前打上标记。后面其实从其他位置出发也能跑到这个格子,这个格子的计数就少了。
那如果我们跑每个点的时候,都对整张地图的
v
i
s
vis
vis 标记
m
e
m
s
e
t
memset
memset 重置一下,那么总的时间复杂度又太大了。
这边可以引入一个类似标记第几个连通块的
i
d
id
id,我们跑每个没有被标记的点,在跑的过程中发现如果能走到的下个点的
v
i
s
vis
vis标记和当前标记不一样,也让它跑下去,并打上当前
i
d
id
id,这样就能统计到所有能够跑到的点。
代码:
#include <bits/stdc++.h>
using namespace std;
int n, m, cnt, ans = 0, num = 0;
char s[1005][1005];
int vis[1005][1005];
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
bool check(int x, int y) {
for (int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (s[nx][ny] == '#') return 0;
}
return 1;
}
void dfs(int x, int y, int id) {
cnt++;
vis[x][y] = id;
if (!check(x, y)) return ;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 1 || nx > n || ny < 1 || ny > m) continue;
// 这边不判s[nx][ny]=='#' 因为前面check有判过了
if (vis[nx][ny] == vis[x][y]) continue;
dfs(nx, ny, id);
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> s[i][j];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (s[i][j] == '.' && !vis[i][j]) {
cnt = 0;
++num;
dfs(i, j, num);
ans = max(ans, cnt);
}
}
cout << ans;
return 0;
}