闭合区域面积统计 题解
题目描述
计算一个 \(10 \times 10\) 矩阵中由 \(1\) 围成的图形的面积。如下所示,在 \(10 \times 10\) 的二维数组中,\(1\) 围住了 \(15\) 个点,因此面积为 \(15\)。
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 0 1 0 0
0 0 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 1 0
0 1 0 1 0 1 0 0 1 0
0 1 0 0 1 1 0 1 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
思路
这道题一开始看上去没啥思路,但仔细想想,是不是拿一桶无限多的水随便往墙(\(1\) 围成的圈子)外的一个地方倒,再统计没有倒上的面积就可以了?
但是有一种例外,比如:
0 0 0 1 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0
0 0 1 0 0 1 0 0 0 0
0 1 0 0 0 1 0 0 0 0
1 0 0 0 0 0 1 0 0 0
0 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
如上,如果我们只在左上角流水,那么水就会被堵住,不能流遍该流到的地方,答案就错了。
这时我们就可以在地图的外圈添加一圈 \(0\),使得所有 \(0\) 都是联通的,水就能流到所有地方了。
代码
#include <bits/stdc++.h>
using namespace std;
bool a[20][20];
struct Node {
int x, y;
};
queue<Node> q;
bool vis[20][20];
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
int main() {
for (int i = 2; i <= 11; i++)
for (int j = 2; j <= 11; j++)
cin >> a[i][j];
q.push({1, 1});
vis[1][1] = 1;
a[1][1] = 1;
while (!q.empty()) {
Node t = q.front();
q.pop();
if (t.x == 12 and t.y == 12) break;
for (int i = 0; i < 4; i++) {
int nx = t.x + dx[i], ny = t.y + dy[i];
if (nx > 12 or nx < 1 or ny > 12 or ny < 1) continue;
if (vis[nx][ny]) continue;
if (a[nx][ny]) continue;
a[nx][ny] = vis[nx][ny] = 1;
q.push({nx, ny});
}
}
int cnt = 0;
for (int i = 1; i <= 12; i++)
for (int j = 1; j <= 12; j++)
if (!a[i][j])
cnt++;
cout << cnt << '\n';
return 0;
}