头像

Cyan

四川成都

深度强化学习炼丹师

2018年第九届蓝桥杯省赛-I.全球变暖

2018年第九届蓝桥杯省赛-I.全球变暖

2022-03-23 · 28次阅读 · 原创 · 数据结构与算法

原题链接

题面

你有一张某海域 NxN 像素的照片,".“表示海洋、”#"表示陆地,如下所示:

.......

.##....

.##....

....##.

..####.

...###.

.......

其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

例如上图中的海域未来会变成如下样子:

.......

.......

.......

.......

....#..

.......

.......

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

输入描述

第一行包含一个整数 N (1N1000)N\ (1 \leq N \leq 1000)

以下 NN 列代表一张海域照片。

照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。、

输出一个整数表示答案。

输入样例

7
.......
.##....
.##....
....##.
..####.
...###.
.......

输出样例

1

题解

DFS,连通性

首先题目要求的是统计原来的岛屿有多少块被淹没,存在以下的特殊情况:

原来存在一块岛屿如下:

........
.##.....
.###....
..#####.
....###.
.....#..
........
........

淹没后变成如下两个岛屿:

........
........
..#.....
........
.....#..
........
........
........

上面虽然淹没后由原来的 1 个岛屿变为了两个岛屿,但其都是原来那个岛屿上的一部分,所以这种情况被完全淹没的岛屿为 0。

我们先通过 DFS 从原来的岛屿的一块陆地出发,标记其经过的陆地为同一块岛屿的编号,就得到了岛屿的数量 tot,而每块陆地都被标记为了 f[i][j],为其所属岛屿的编号。之后,我们将四周存在海洋的陆地淹没,将剩余的陆地的编号统计起来,其编号种数就是剩下的原来的岛屿个数,再由原来的岛屿数量减去剩余的原岛屿的数量则为被完全淹没的岛屿数量。

代码

#include<bits/stdc++.h> using namespace std; typedef pair<int, int> PII; const int N = 1005; int n, tot, f[N][N], dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; bool v[N][N]; char g[N][N], s[N][N]; void dfs(int i, int j) { f[i][j] = tot; //标记这是第几块陆地的一部分 for (int d = 0; d < 4; d++) { //遍历四个方向 int ti = dir[d][0] + i, tj = dir[d][1] + j; if (ti < 0 || ti >= n || tj < 0 || tj >= n) continue; if (g[ti][tj] == '#' && !v[ti][tj]) { //当前为陆地,且未访问过 v[ti][tj] = true; dfs(ti, tj); } } } int main() { cin >> n; for (int i = 0; i < n; i++) scanf("%s", g[i]); //统计原始的陆地数目 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (g[i][j] == '#' && !v[i][j]) { ++tot; v[i][j] = true; dfs(i, j); } } } memcpy(s, g, sizeof g); //将旧地图 g 复制给 新地图s for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (g[i][j] == '.') continue; for (int d = 0; d < 4; d++) { int ti = dir[d][0] + i, tj = dir[d][1] + j; if (ti < 0 || ti >= n || tj < 0 || tj >= n) continue; //原始地图的陆地g(i, j)区域四周存在海洋,则新地图 s(i, j)区域被淹没为海洋 if (g[ti][tj] == '.') { s[i][j] = '.'; break; } } } } //计算剩余的陆地的标记数目,则可知道还剩下多少块原来的陆地没有被淹没 set<int> st; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (s[i][j] == '#') st.insert(f[i][j]); } } cout << tot - st.size() << endl; return 0; }

标题: 2018年第九届蓝桥杯省赛-I.全球变暖
链接: https://www.fightingok.cn/detail/209
更新: 2022-09-18 22:48:24
版权: 本文采用 CC BY-NC-SA 3.0 CN 协议进行许可