1233-全球变暖

题目描述

关系

内容

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

.......
.
.
....
..
...
.......

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

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。

具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

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

.......
.......
.......
.......
....
.......
.......

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

输入格式

第一行包含一个整数N。

以下 NN 列,包含一个由字符”#”和”.”构成的 N×N 字符矩阵,代表一张海域照片,”#”表示陆地,”.”表示海洋。

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

输出格式

一个整数表示答案。

数据范围

1N1000

输入样例1:

7
.......
.
.
....
..
...
.......

输出样例1:

1

输入样例2:

9
.........
.
.
.
.........
.
.
.
.........

输出样例2:

1

问题分析

最初思路

分成三步:

  1. 遍历矩阵,找到所有的岛屿,并把这些岛屿的位置,并统计岛屿的数量 a;
  2. 模拟,将所有环海的块,替换成海洋;
  3. 再次遍历矩阵,重新计算岛屿的数量 b;
  4. 最后 a - b 就是最终的答案;

思路分析

这道题是一道典型的 flood fill 的模板题。flood fill 有两种经典实现方式,一种是 bfs,一种是 dfs。这道题使用的是 bfs。

执行流程设计

  1. 遍历,通过 bfs 找到连通块的数量;
    1. 在 bfs 过程中,统计连通块的数量 total;
    2. 统计有多少块是与海相邻的,数量为 count;
  2. 若 total == count,那么这个岛屿就会被淹没,让答案++即可;

总结

代码实现

#include <bits/stdc++.h>
using namespace std;

#define x first
#define y second

typedef pair<int, int> pii;

const int N = 1010;
int n, ans;
char ma[N][N];
bool st[N][N];
int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};

void bfs(pii start, int &total, int &bound) 
{
    queue<pii> q;
    q.push(start);
    st[start.x][start.y] = true;
    
    while (!q.empty()) {
        pii u = q.front();
        q.pop();
        
        for (int i = 0; i < 4; i++) {
            int x = u.x + dx[i], y = u.y + dy[i];
            
            if (x < 0 || y < 0 || x >= n || y >= n) continue;
            if (ma[x][y] != '#') continue;
            if (st[x][y]) continue;
            
            total++;
            st[x][y] = true;
            for (int i = 0; i < 4; i++) {
                int xx = x + dx[i], yy = y + dy[i];
                if (xx < 0 || yy < 0 || xx >= n || yy >= n) continue;
                
                if (ma[xx][yy] == '.') {
                    bound++;
                    break;
                }
            }
            
            q.push({x, y});
        }
    }
}

void solve()
{
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (!st[i][j] && ma[i][j] == '#') {
                int total = 0, bound = 0;
                bfs({i, j}, total, bound);
                
                if (total == bound) ans++;
            }
        }
    }
    
    cout << ans << endl;
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) cin >> ma[i];
    
    solve();
    return 0;
}