洛谷 P1162 填涂颜色
题目链接:填涂颜色
思路
因为需要找出被所有1围住的0,但是发现直接查找会比较麻烦,会需要搜索判断四个方向都被1包围,然后还要再次搜素给这些0赋值。但是如果反向思维把不被1包围的0全部找出来剩下的就是被1包围的0了,可以使用搜索从在正方形边界上的0开始搜索,将所有能搜到的0全部标记,剩下的就是被1包围的0。
此时我们把地图的边界扩大2个格子从(1 - n) -> (0 - n + 1),此时就不需要一个个去判断在边界上的元素是否是0了,因为可以直接从(0, 0)开始搜索,整个方阵周围多了一圈0,所以在方阵边界上的元素是0时,可以直接被搜索到。至于为什么不用(0 - n),因为可能会出现特殊情况导致方阵右下角未1包围的0没有被搜索到,如下图右下角的四个0就不会被搜索到,会被判定为被1包围的0。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 30 + 10;
#define ll long long
int mp[N][N], dir[5][2] = {
{ 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 }
}, n;
bool vis[N][N];
bool check(int x, int y) {
return x >= 0 && x <= n + 1 && y >= 0 && y <= n + 1;
}
bool BFS(int x, int y) {
queue<pair<int, int>> q;
q.push({x, y});
while (!q.empty()) {
pair<int, int> point = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
pair<int, int> dpoint = point;
dpoint.first = point.first + dir[i][0];
dpoint.second = point.second + dir[i][1];
if (check(dpoint.first, dpoint.second)) {
if (mp[dpoint.first][dpoint.second] == 0) {
mp[dpoint.first][dpoint.second] = 3;
q.push(dpoint);
}
}
}
}
return true;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> mp[i][j];
}
}
BFS(0, 0);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (mp[i][j] == 3) {
cout << 0 << " ";
} else if (mp[i][j] == 0) {
cout << 2 << " ";
} else {
cout << 1 << " ";
}
}
cout << endl;
}
return 0;
}