【天梯赛】L2-048 寻宝图 (DFS做法)

简介: 遇到一个非'0'字符(也就是'1'和 宝藏'2'到'9')就让ans++,同时将这个非'0'字符染色为'0',然后往四个方向(上、下、左、右)搜索,这里的目的是那一片岛屿(也就是那一片为'1'的部分)都染色为‘0’。本题就请你统计一下,给定的地图上一共有多少岛屿,其中有多少是有宝藏的岛屿。为了判断有宝藏的岛屿,这里我开了一个全局变量f来判断这一片岛屿是否有宝藏(也就是有无字符'2'-'9'),当搜到字符'2'~'9'时就将f标记为1。在一行中输出 2 个整数,分别是岛屿的总数量和有宝藏的岛屿的数量。

1. 题目描述

给定一幅地图,其中有水域,有陆地。被水域完全环绕的陆地是岛屿。有些岛屿上埋藏有宝藏,这些有宝藏的点也被标记出来了。本题就请你统计一下,给定的地图上一共有多少岛屿,其中有多少是有宝藏的岛屿。

输入格式:
输入第一行给出 2 个正整数 N 和 M(1<N×M≤105),是地图的尺寸,表示地图由 N 行 M 列格子构成。随后 N 行,每行给出 M 位个位数,其中 0 表示水域,1 表示陆地,2-9 表示宝藏。
注意:两个格子共享一条边时,才是“相邻”的。宝藏都埋在陆地上。默认地图外围全是水域。

输出格式:
在一行中输出 2 个整数,分别是岛屿的总数量和有宝藏的岛屿的数量。

输入样例:

10 11
01000000151
11000000111
00110000811
00110100010
00000000000
00000111000
00114111000
00110010000
00019000010
00120000001

输出样例:

7 2

2. 思路分析

联通块flood-fill问题。这题需要特别注意 1<N×M≤10^5 这个条件,所以我们不能用二维数组来直接存储(因为有可能其中一维为10^5,另一维为1,所以理论上二维数组每一维都要为10^5,但是很明显会爆,二维数组开不了这么大的空间(也就不能用二维数组读入,也不能开一个二维数组来标记,所以我就用了“染色”的思想)...为了解决这个问题,这题我采用了每一行用一个字符串存储来读入)。

联通块问题可以用DFS或BFS来解决。这里我用了深度优先搜索DFS,用ans统计总岛屿数量,ans1统计有宝藏的岛屿数量。遇到一个非'0'字符(也就是'1'和 宝藏'2'到'9')就让ans++,同时将这个非'0'字符染色为'0',然后往四个方向(上、下、左、右)搜索,这里的目的是那一片岛屿(也就是那一片为'1'的部分)都染色为‘0’。

为了判断有宝藏的岛屿,这里我开了一个全局变量f来判断这一片岛屿是否有宝藏(也就是有无字符'2'-'9'),当搜到字符'2'~'9'时就将f标记为1。

为了实现上、下、左、右搜索,这里我开了两个方向数组dx[ ]和dy[ ] 存储坐标(x,y)上、下、左、右 表示下一步能到的位置。如果越界或者下一步搜到字符'0'时就跳过。

每次搜索完时,如果f为1,就让ans1++,同时再将f置为0,便于以后的搜索。

3. 代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int N = 1e5+10;
int n, m;
ll ans, ans1;
string g[N];
int dx[] = {
    -1,1,0,0 };
int dy[] = {
    0,0,-1,1 };
int f;

void dfs(int x, int y) {
   
    if (g[x][y] >= '2' && g[x][y] <= '9') f = 1;
    g[x][y] = '0';
    for (int i = 0; i < 4; i++) {
   
        int nx = x + dx[i], ny = y + dy[i];
        if (nx<0 || nx>n - 1 || ny<0 || ny>m - 1) continue;
        if (g[nx][ny] == '0') continue;
        dfs(nx, ny);
    }
    return;
}

int main() {
   
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> m;
    for (int i = 0; i < n; i++) cin >> g[i];
    for (int i = 0; i < n; i++) {
   
        for (int j = 0; j < m; j++) {
   
            if (g[i][j] != '0') {
   
                dfs(i, j);
                ans++;
            }
            if (f) {
   
                ans1++;
                f = 0;
            }
        }
    }
    cout << ans << " " << ans1 << endl;
    return 0;
}

相关文章
|
JSON 程序员 数据格式
深入探索 “JSON for Modern C++“:安装、构建与应用
深入探索 “JSON for Modern C++“:安装、构建与应用
502 0
|
Web App开发 安全 网络协议
Qt开发技术:QWebSocket客户端、服务端介绍与开发
Qt开发技术:QWebSocket客户端、服务端介绍与开发
Qt开发技术:QWebSocket客户端、服务端介绍与开发
|
C++
【天梯赛】L2-045 堆宝塔
最后 A 柱上剩下的宝塔作为一件成品,B 柱上剩下的彩虹圈被逐一取下,堆成另一座宝塔。堆宝塔游戏是让小朋友根据抓到的彩虹圈的直径大小,按照从大到小的顺序堆起宝塔。但彩虹圈不一定是按照直径的大小顺序抓到的。第二行按照宝宝抓取的顺序给出 N 个不超过 100 的正整数,对应每个彩虹圈的直径。//定义一个栈,T可以为int,float,double,char,string......在一行中输出宝宝堆出的宝塔个数,和最高的宝塔的层数。//检查栈是否为空,如果为空返回true,否则返回false。
302 8
|
存储 人工智能 C++
【PTA】L1-064 估值一亿的AI核心代码(详C++)
【PTA】L1-064 估值一亿的AI核心代码(详C++)
575 1
|
存储 前端开发 中间件
『软件工程10』结构化系统分析:数据流图和字典案例分析
该文章通过具体案例分析了在软件工程中如何运用数据流图和数据字典来进行结构化系统分析,帮助明确系统的信息流程和数据定义。
『软件工程10』结构化系统分析:数据流图和字典案例分析
|
存储 算法 Java
【DFS(深度优先搜索)详解】看这一篇就够啦
本文介绍了深度优先搜索(DFS)算法及其应用。DFS从某个顶点出发,深入探索图的每条路径,直到无法前进为止,然后回溯。文章详细解释了DFS的基本思想,并通过示例图展示了其执行过程。此外,文中还探讨了三种枚举方式:指数型枚举、排列型枚举和组合型枚举,并提供了具体的代码实现。最后,文章通过几道练习题帮助读者更好地理解和应用DFS算法。
10714 19
【DFS(深度优先搜索)详解】看这一篇就够啦
|
关系型数据库 MySQL Linux
Linux 安装 mysql 【使用 tar.gz | tar.xz安装包-离线安装】
在Linux系统中使用tar.xz压缩包安装MySQL数据库的详细步骤。包括下载MySQL压缩包,解压到指定目录,创建mysql用户和组,设置目录权限,初始化MySQL,配置my.cnf文件,启动服务,以及修改root用户密码。此外,还提供了如何设置Windows远程登录MySQL服务器的方法。
Linux 安装 mysql 【使用 tar.gz | tar.xz安装包-离线安装】
|
机器学习/深度学习 并行计算 PyTorch
从零开始下载torch+cu(无痛版)
这篇文章提供了一个详细的无痛版教程,指导如何从零开始下载并配置支持CUDA的PyTorch GPU版本,包括查看Cuda版本、在官网检索下载包名、下载指定的torch、torchvision、torchaudio库,并在深度学习环境中安装和测试是否成功。
从零开始下载torch+cu(无痛版)
|
关系型数据库 MySQL 数据库
MySQL忘记密码的处理方法(MySQL重置密码)
本文主要讲解MySQL如何重置密码(MySQL密码重置方法)
91844 2
MySQL忘记密码的处理方法(MySQL重置密码)
编译原理——构造预测分析表(判断某字符串是否是文法G(E)的句子)
编译原理——构造预测分析表(判断某字符串是否是文法G(E)的句子)
420 0