P8662 [蓝桥杯 2018 省 AB] 全球变暖

 题目描述

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

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

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

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

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

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

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

输入格式

第一行包含一个整数 N。(1≤N≤1000)。

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

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

输出格式

一个整数表示答案。

输入输出样例

输入 #1复制

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

输出 #1复制

1

说明/提示

时限 1 秒, 256M。蓝桥杯 2018 年第九届省赛

代码解析+注释 

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

// 定义最大网格尺寸
const int N = 1e3 + 10;

// 定义网格数组和相关变量
char a[N][N];    // 存储网格
int n, ans;      // n: 网格的大小,ans: 满足条件的区域数量
// xx[], yy[] 用于表示四个方向:下、上、右、左
int xx[] = {1, -1, 0, 0};
int yy[] = {0, 0, 1, -1};

// vis[] 数组用于标记某个位置是否已被访问过
bool v = 1, vis[N][N];

// 检查当前位置是否是 '#'
bool ok(int x, int y) {
    return a[x][y] != '.';  // 如果当前格子是 '#', 返回true,否者返回false
}

// 深度优先搜索(DFS)函数,遍历与当前格子相连的所有 '#'
bool dfs(int x, int y) {
    vis[x][y] = 1;  // 标记当前位置已访问
    // 如果当前格子的四个方向(上下左右)都被 '#' 包围
    if (ok(x-1, y) && ok(x+1, y) && ok(x, y+1) && ok(x, y-1))
        v = 0;  // 如果四个方向都被 '#' 围住,表示不符合条件,设置 v = 0

    // 遍历四个相邻的格子
    for (int i = 0; i < 4; i++) {
        int X = x + xx[i], Y = y + yy[i];  // 计算相邻位置的坐标
        // 如果相邻格子是 '#' 且没有被访问过
        if (ok(X, Y) && !vis[X][Y]) {
            dfs(X, Y);  // 递归地访问相邻格子
        }
    }

    a[x][y] = '.';  // 当前格子处理完毕,标记为 '.',表示已处理
    return v;  // 返回是否符合条件的标志
}

signed main() {
    cin >> n;  // 输入网格的大小 n
    // 输入网格的内容
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> a[i][j];  // 读取网格每个位置的值
        }
    }

    // 遍历整个网格
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            // 如果当前位置是 '#'
            if (ok(i, j)) {
                v = 1;  // 假设满足条件
                ans += dfs(i, j);  // 调用DFS,递归遍历当前区域
            }
        }
    }

    cout << ans << endl;  // 输出满足条件的区域数量
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值