【模拟】扫雷
一、题目描述
在一个 n n n 行 m m m 列的方格图上有一些位置有地雷,另外一些位置为空。
请为每个空位置标一个整数,表示周围八个相邻的方格中有多少个地雷。
1.1 输入描述
输入的第一行包含两个整数 n , m n, m n,m。
第 2 2 2 行到第 n + 1 n + 1 n+1 行每行包含 m m m 个整数,相邻整数之间用一个空格分隔。如果对应的整数为 0 0 0,表示这一格没有地雷。如果对应的整数为 1 1 1,表示这一格有地雷。
其中, 1 ≤ n , m ≤ 100 1 \leq n, m \leq 100 1≤n,m≤100。
1.2 输出描述
输出 n n n 行,每行 m m m 个整数,相邻整数之间用空格分隔。
对于没有地雷的方格,输出这格周围的地雷数量。对于有地雷的方格,输出 9 9 9。
1.3 输入输出样例
- 输入:
3 4
0 1 0 0
1 0 1 0
0 0 1 0
- 输出:
2 9 2 1
9 4 9 2
1 3 9 2
原题链接:扫雷
二、解题思路
2.1 整体做事流程
就像咱们玩扫雷游戏一样,现在要处理一个方格图。首先得知道这个方格图多大(也就是读入行数
n
和列数m
),然后把每个格子有没有雷的信息存下来。接下来,逐个检查每个格子:
- 如果这个格子本身有雷(存的是
1
),直接标个9
就行,这是题目规定的 - 如果这个格子没雷(存的是
0
),就得数它周围八个格子里有多少雷,把这个数字标上去。最后把处理好的整个方格图打印出来。
2.2 关键细节怎么处理
-
找周围八个格子:
不管当前格子在哪,都要找它周围八个方向的格子。比如,当前格子在中间,上下左右斜着都能找;但如果在最左边,左边没格子了,就不找左边。所以得给行和列算个“安全范围”:- 行的范围:最小不低于
0
(比如i-1
算出来负数,就取0
),最大不超过方格图的最后一行(比如i+1
超过行数,就取最大合法行号) - 列的范围:和行一样的道理,最小不低于
0
,最大不超过最后一列
- 行的范围:最小不低于
这样循环找周围格子时,就不会“跑出去”越界了。
- 数雷的数量:
找到周围八个格子后,逐个看这些格子有没有雷(看存的是不是1
),每发现一个雷,当前格子要标的数字就加1
。
三、代码详解
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int re1[N][N], re2[N][N];
int main()
{
int n, m;
cin >> n >> m;
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
cin >> re1[i][j];
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(re1[i][j] == 1){
re2[i][j] = 9;
continue;
}
else{
for(int i1 = max(0, i-1); i1 <= min(i+1, n); i1++){
for(int j1 = max(0, j-1); j1 <= min(j+1, n); j1++){
if(re1[i1][j1] == 1){
re2[i][j] += 1;
}
}
}
}
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
cout << re2[i][j] << ' ';
}
cout << '\n';
}
return 0;
}
3.1 变量定义
const int N = 110;
:定义数组大小,适配题目中 n , m n, m n,m 最大为 100 100 100 的限制int re1[N][N], re2[N][N];
:re1
用于存储输入的地雷分布,re2
存储处理后的结果
3.2 输入数据
通过两层循环读取
n
n
n 行
m
m
m 列的地雷分布数据,存入 re1
数组
3.3 处理每个格子
- 判断地雷:若
re1[i][j] == 1
,直接将re2[i][j]
设为 9 9 9 - 统计周围地雷:
- 外层循环确定行坐标范围:
max(0, i-1)
确保不越界,min(i+1, n-1)
保证不超过数组最大下标 - 内层循环确定列坐标范围:同理处理列坐标边界
- 若遍历到的格子
re1[i1][j1] == 1
,则当前格子的统计数re2[i][j]
加 1 1 1
- 外层循环确定行坐标范围:
3.4 输出结果
最后通过两层循环,按行输出 re2
数组的内容,每个元素后加空格,每行结束换行
微语录:我现在虽没到达终点,但至少比昨天更接近一些。