题目:
在一个n行m列的方格图上有一些位置有地雷,另外一些位置为空。
请为每个空位置标一个整数,表示周围八个相邻的方格中有多少个地雷。
【输入】
输入的第一行包含两个整数n,m。
第2行到第n+1行每行包含m个整数,相邻整数之间用一个空格分隔。如果对应的整数为0,表示这一格没有地雷。如果对应的整数为1,表示这一格有地雷。
其中,1≤n,m≤100。
【输出】
输出n行,每行m个整数,相邻整数之间用空格分隔。
对于没有地雷的方格,输出这格周围的地雷数量。对于有地雷的方格,输出9。
【输入样例】
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
答案:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, m, cnt; // 声明整数 n, m 用于表示二维数组的行和列,cnt 用于计数
int a[110][110] = { 0 }; // 初始化一个 110x110 的二维数组,所有元素都设置为 0
cin >> n >> m; // 从标准输入读取 n(行数)和 m(列数)
// 使用输入的值填充二维数组
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> a[i][j]; // 将每个元素读入数组
}
}
// 定义数组以表示 8 个相邻单元格的相对位置
int dx[8] = { 0, 1, 1, 1, 0, -1, -1, -1 };
int dy[8] = {-1, -1, 0, 1, 1, 1, 0, -1 };
// 处理数组的每一个单元格
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (a[i][j] == 1) // 如果当前单元格的值为 1
{
cout << 9 << " "; // 打印 9 和一个空格(具体问题的规则可能会要求这样做)
continue; // 继续下一次迭代
}
cnt = 0; // 重置邻近的 1 的计数
// 循环遍历 8 个方向
for (int k = 0; k < 8; k++)
{
int new_i = i + dx[k]; // 通过添加第 k 个 dx 值计算新的 i 坐标
int new_j = j + dy[k]; // 通过添加第 k 个 dy 值计算新的 j 坐标
// 如果新坐标在数组边界之外,继续下一次循环
if (new_i < 0 || new_j < 0 || new_i >= n || new_j >= m)
continue;
// 如果相邻单元格包含 1,则增加计数
if (a[new_i][new_j] == 1)
cnt++;
}
cout << cnt << " "; // 打印该单元格的邻近 1 的计数和一个空格
}
cout << endl; // 在处理完一行后,输出换行符
}
return 0;
}
注:
int dx[8] = { 0, 1, 1, 1, 0, -1, -1, -1 };
int dy[8] = {-1, -1, 0, 1, 1, 1, 0, -1 };
这里,dx
和 dy
数组代表一个单元格相对于其八个可能的邻近单元格的位置偏移:上,右上,右,右下,下,左下,左和左上。
例如,第一个 dx[0], dy[0]
对表示向右移动零列(dx[0]
)和向上移动一行(dy[0]
)。这意味着我们在查看上方的邻居。
当涉及循环时:
for (int k = 0; k < 8; k++)
{
int new_i = i + dx[k];
int new_j = j + dy[k];
// 如果超出了边界,跳过,防止访问到无效内存。
if (new_i < 0 || new_j < 0 || new_i >= n || new_j >= m)
continue;
// 如果相邻单元格包含 1,增加计数。
if (a[new_i][new_j] == 1)
cnt++;
}
程序对于不是 1
的每个单元格 a[i][j]
执行以下操作:
- 循环通过
dx
和dy
数组查看每一个邻近的 8 个单元格。 - 计算
new_i
和new_j
,它们是这些邻居之一的坐标。 - 检查是否
new_i
或new_j
超出了数组的边界。如果是,跳转到下一个邻居。 - 如果邻居单元格在边界内且含有
1
,增加计数1
的数量。
遍历所有 8 个可能邻居后,它会打印出该单元格的计数。
例如,如果当前单元格 a[i][j]
在网格中的坐标是 [2,2],那么遍历 k
的循环将检查 [2,1](上),[3,1](右上)...等单元格。如果位置有效并且单元格内容是 1
,就会增加该单元格的计数。
最后,当 j
上的内层循环完成后(表示一行的结束),会打印出一个换行符来正确格式化输出,分隔各行。