AT_arc041_b 题解
本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读。
题目简述
给定一个 \(N \times M\) 的矩阵,此矩阵的每一个元素都向上、下、左、右 \(4\) 个方向同时扩散(原来的位置不保留)。
现给出原矩阵扩散后的矩阵,求原矩阵。
思路
对于扩散后的 \((i,j)\),是原矩阵的 \((i-1,j)\),\((i+1,j)\),\((i,j-1)\),\((i,j+1)\) 扩散而来的,那么就可以通过这 \(4\) 个点推断出原矩阵上 \((i,j)\) 的数。
例如:
010
101
010
这个样例中,只有 \((2,2)\) 周围 \(4\) 个方向都是非 \(0\) 数,所以从这个例子中就可推出计算原矩阵上 \((i,j)\) 的数的方程式了:
\[(i,j)=\min(\min((i-1,j),(i+1,j),\min((i,j-1),(i,j+1)))
\]
那么就会产生一个疑问,对于边界有没有特殊情况?比如对于 \((1,1)\) 他的方程式带入就为:
\[(1,1)=\min(\min((0,1),(2,1)),\min((1,0),(1,2)))
\]
所以对于边界 \((0,1)\) 和 \((1,0)\) 的初始化就尤为重要,这里建议初始化为 \(0\),这样取 \(\min\) 之后就为 \(0\) 了。
处理完边界的初始化之后基本就没什么了,不过我们还是要思考一下,比如对于以下情况:
0000000
0001000
0030400
0209030
0050600
0003000
0000000
\((2,3)\) 并不是边界并且也不满足四周都是非 \(0\) 数,那么它是不是一种特殊情况?会不会不满足上面推出的方程式?答案是肯定的,因为 \((2,3)\) 的上、左两个方向的数是 \(0\),则取 \(\min\) 之后就一定为 \(0\) 了。
经过以上分析以及一些证明,基本就有大致的代码框架了:
#include<iostream>
using namespace std;
int n, m, mp[505][505]; // mp 记录地图
char c; // 临时储存
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++) {
cin >> c;
mp[i][j] = c - '0'; // 转化为数字
}
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) {
int minn = min(min(mp[i - 1][j], mp[i + 1][j]), min(mp[i][j - 1], mp[i][j + 1])); // 计算 minn 值
cout << minn; // 可直接输出
// 把周围扩散的数减去
mp[i - 1][j] -= minn; mp[i + 1][j] -= minn;
mp[i][j - 1] -= minn; mp[i][j + 1] -= minn;
}
cout << endl; // 记得换行
}
return 0;
}
\[\text{The End!}
\]
本文来自博客园,作者:So_noSlack,转载请注明原文链接:https://www.cnblogs.com/So-noSlack/p/17582638.html