[蓝桥杯 2018 省 AB] 全球变暖
题目描述
你有一张某海域
N
×
N
N \times N
N×N 像素的照片,.
表示海洋、 #
表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中 “上下左右” 四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 2 2 座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
输入格式
第一行包含一个整数 N N N。 ( 1 ≤ N ≤ 1000 ) (1 \le N \le 1000) (1≤N≤1000)。
以下 N N N 行 N N N 列代表一张海域照片。
照片保证第 1 1 1 行、第 1 1 1 列、第 N N N 行、第 N N N 列的像素都是海洋。
输出格式
一个整数表示答案。
样例 #1
样例输入 #1
7
.......
.##....
.##....
....##.
..####.
...###.
.......
样例输出 #1
1
提示
时限 1 秒, 256M。蓝桥杯 2018 年第九届省赛
思路
首先,定义一个二维数组m1
来存储海洋和陆地的地图,其中海洋用.
表示,陆地用#
表示。然后,定义一个二维数组vis
来存储每个位置是否已经访问过。
在主函数中,首先读取地图的大小n
,然后读取地图。接着,通过DFS统计原始地图中岛屿的数量,存储在begin
中。随后,执行淹没操作,模拟全球变暖后海洋上升,陆地被淹没的情况。最后,再次通过DFS统计淹没后剩下的岛屿数量,存储在end
中。最后,输出被完全淹没的岛屿数量,即begin - end
。
在DFS过程中,定义了两个函数:cntIs
和submerge
。cntIs
函数用于统计岛屿数量,submerge
函数用于模拟陆地被淹没的过程。每次DFS前,都需要重置访问数组vis
,以防止重复访问。
在cntIs
函数中,首先检查当前位置是否访问过或者是否为海洋,如果是,则直接返回。然后,设置当前位置已访问,并检查当前位置是否为陆地。接着,遍历当前位置的四个方向,如果邻居是陆地,则递归调用cntIs
函数。
在submerge
函数中,首先检查当前位置是否访问过或者是否为海洋,如果是,则直接返回。然后,设置当前位置已访问。接着,遍历当前位置的四个方向,如果邻居是海洋,则将当前位置标记为淹没,并退出循环。如果当前位置被淹没,则遍历其四个方向,如果邻居是陆地,则递归调用submerge
函数。
注意
需要将被淹没的陆地标记为其他字符(这里将被淹没的陆地标记为了*
)。否则,如果在海平面上升过程中,某个大岛被部分淹没后,分裂成几个小岛,会出现海平面上升后的岛屿数量比上升前的多,导致答案出现负数。
AC代码
#include <algorithm>
#include <bitset>
#include <iostream>
#define mp make_pair
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;
const int N = 1e3 + 7;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int n;
char m1[N][N];
bitset<N> vis[N];
void resetVis() {
for (int i = 1; i <= n; i++) {
vis[i].reset();
}
}
bool cntIs(int x, int y) {
if (vis[x][y] || m1[x][y] == '.') {
return 0;
}
vis[x][y] = 1;
bool flg = (m1[x][y] == '#');
for (int i = 0; i < 4; i++) {
int x1 = x + dir[i][0];
int y1 = y + dir[i][1];
if (1 <= x1 && x1 <= n && 1 <= y1 && y1 <= n && m1[x1][y1] != '.') {
flg |= cntIs(x1, y1);
}
}
return flg;
}
// 如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
void submerge(int x, int y) {
if (vis[x][y] || m1[x][y] != '#') {
return;
}
vis[x][y] = 1;
for (int i = 0; i < 4; i++) {
int x1 = x + dir[i][0];
int y1 = y + dir[i][1];
if (1 <= x1 && x1 <= n && 1 <= y1 && y1 <= n && m1[x1][y1] == '.') {
// 靠海,直接淹没
m1[x][y] = '*';
break;
}
}
if (m1[x][y] == '*') {
// 沿海边拓展
for (int i = 0; i < 4; i++) {
int x1 = x + dir[i][0];
int y1 = y + dir[i][1];
if (1 <= x1 && x1 <= n && 1 <= y1 && y1 <= n && m1[x1][y1] == '#') {
submerge(x1, y1);
}
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> m1[i][j];
}
}
int begin = 0;
resetVis();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
begin += cntIs(i, j);
}
}
resetVis();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
submerge(i, j);
}
}
int end = 0;
resetVis();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
end += cntIs(i, j);
}
}
// cout << begin << " " << end << "\n";
cout << (begin - end) << "\n";
return 0;
}
“这颗星球正在沉没——”
“海平面因不明原因急速上升,海洋吞没了大部分沿海地区,如今也不断蚕食着陆地。”
“人类的栖息地被迫收缩,处于巅峰的科学技术渐渐流失。”
“这是缓步迈向灭亡的平静时代。”
“我与他邂逅了。”
“他说自己必须拯救地球——”
“于是我问道。”
“——地球也包括我吗……?”
“我守望着。”
“守望着渐渐沉没的地球。”
“守望着反抗灭亡的宿命,奋力挣扎的人们。”
“身处无限的孤独之中……”
“时间流逝吧,你是多么的残酷——”