202606-扫雷(luogu-B4557)

202606-扫雷(luogu-B4557)

GESP C++四级2026年6月真题。本题主要考查二维数组的使用和八方向邻域遍历。属于四级题中的基础题目。难度⭐⭐。本题在洛谷评定为普及-

luogu-B4557 [GESP202606 四级] 扫雷

题目要求

题目描述

小杨同学正在游玩经典游戏「扫雷」,他想自己生成一个「扫雷」的地图。

小杨同学希望生成的地图大小为 nnmm 列,一共 n×mn \times m 个区块。区块行号为 1,2,,n1, 2, \cdots, n,列号为 1,2,,m1, 2, \cdots, m。其中一些区块为雷区,其它区块不为雷区。

小杨同学指定了 qq 个区块为雷区,而其它区块均不为雷区。小杨同学希望你帮忙计算非雷区的区块,每个区块与多少个雷区相邻?

我们定义区块相邻,当且仅当两个区块至少有一个公共顶点(也就是说对于不在地图边缘的区块,周围 88 个区块均与其相邻)。

输入格式

输入包含 q+1q + 1 行。

第一行,三个正整数 nn, mmqq,分别表示地图行数和列数,以及雷区数量。

接下来的 qq 行,每行有 22 个整数,分别表示第 ii 个雷区的行号和列号。

保证输入的雷区不重复。

输出格式

输出 nn 行,每行 mm 个字符(使用空格分割),对于第 ii 行第 jj 列,输出地图对应区块的信息:

  1. 如果为雷区,输出 *
  2. 如果不是雷区,输出其相邻雷区数量(输出 0088 中的一个数字)。

输入输出样例 #1

输入 #1
3 4 4
1 1
1 3
2 4
3 2
输出 #1
* 2 * 2
2 3 3 *
1 * 2 1

说明/提示

根据输入,在 3×43 \times 4 的地图上有 44 个雷区,分别是 (1,1)(1,1)(1,3)(1,3)(2,4)(2,4)(3,2)(3,2),如输出样例中 * 所示,其它非雷区区块的相邻雷区数量可以直观看出。

数据范围

3n,m5003 \le n, m \le 500, 1qnm1 \le q \le n \cdot m

输入的雷区必定在地图内且不重复,注意行号和列号均从 11 开始。


题目分析

本题是经典的扫雷地图生成问题,主要考察二维数组的使用和八方向邻域遍历。难度不高,属于模拟类题目。

1. 数据结构设计

  • 使用二维布尔数组 mine[505][505] 记录每个位置是否为雷区
  • 使用方向数组 dx[8]dy[8] 表示八个方向的偏移量,便于遍历邻域
  • 数组大小设置为 505 是为了满足题目要求的最大范围(n,m500n, m \leq 500),并留有余量

2. 核心算法思路

  • 首先读入地图大小 nnmm 和雷区数量 qq
  • 将所有雷区位置标记在二维数组中
  • 遍历整个地图的每个位置,如果是雷区,输出 *;如果不是雷区,遍历周围 88 个方向,统计相邻的雷区数量并输出
  • 注意边界判断:邻域坐标必须在 [1,n]×[1,m][1, n] \times [1, m] 范围内

3. 算法复杂度分析

  • 时间复杂度:标记雷区 O(q)O(q),遍历地图并统计 O(n×m)O(n \times m),总体 O(n×m)O(n \times m)
  • 空间复杂度:存储地图信息 O(n×m)O(n \times m),总体 O(n×m)O(n \times m)

示例代码

#include <iostream>

// 二维数组记录每个位置是否为雷区
bool mine[505][505];

// 八个方向的偏移量:上、下、左、右、左上、右上、左下、右下
int dx[8] = {-1, 1, 0, 0, -1, -1, 1, 1};
int dy[8] = {0, 0, -1, 1, -1, 1, -1, 1};

int main() {
    // 读入地图行数、列数和雷区数量
    int n, m, q;
    std::cin >> n >> m >> q;

    // 读入每个雷区的位置并标记
    for (int i = 0; i < q; i++) {
        int r, c;
        std::cin >> r >> c;
        mine[r][c] = true;
    }

    // 遍历整个地图
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            // 输出元素之间的空格分隔
            if (j > 1) {
                std::cout << " ";
            }
            if (mine[i][j]) {
                // 当前位置是雷区,输出 '*'
                std::cout << "*";
            } else {
                // 当前位置不是雷区,统计周围 8 个方向的雷区数量
                int count = 0;
                for (int d = 0; d < 8; d++) {
                    int ni = i + dx[d];
                    int nj = j + dy[d];
                    // 判断邻域坐标是否在地图范围内
                    if (ni >= 1 && ni <= n && nj >= 1 && nj <= m && mine[ni][nj]) {
                        count++;
                    }
                }
                std::cout << count;
            }
        }
        std::cout << std::endl;
    }
    return 0;
}

本文由coderli.com原创,按照CC BY-NC-SA 4.0 进行授权

所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code

luogu-”系列题目可在 洛谷题库 在线评测。

bcqm-”系列题目可在 编程启蒙题库 在线评测。

GESP/CSP认证交流QQ群: 688906745

GESP/CSP 认证学习微信公众号
GESP/CSP 认证学习微信公众号
最后更新于