AcWing 3149. 打印十字图
原题链接
简单
作者:
fanogy
,
2021-03-14 17:46:15
,
所有人可见
,
阅读 979
算法1
模拟 $O(m^2 * n)$
1.对于给定的层数 $n$,不难发现,矩阵长度 $m$ 满足 $m = (n - 1) * d + 9$, 其中公差$d = 2$,首项 $a1 = 9$。
2.不妨从中心开始逐步向外递推,可以发现,一旦确定了中间的十字形状,与其相邻的 $8$个方位都为 $’.’$, 而与 $’.’$ 相邻的8个方位均为’$’。因此,我们可以通过n次迭代,确定n层形状。具体做法是,每次扫描整个矩阵两遍,对于没有确定的位置,将其更改为与其相邻且已确定位置的反值。
3.最后,只需要将四个$2*2$的小矩阵修改为$’.’$即可。
C++ 代码
#include <iostream>
using namespace std;
char g[130][130];
int dirx[] = {-1,0,0,1,1,-1,-1,1}; //八方位
int diry[] = {0,1,-1,0,1,-1,1,-1};
int n;
int main() {
scanf("%d", &n);
int m = 4 * n + 5;
int center = m / 2; //中心点,即十字
for(int i = 0; i < m; i++) for(int j = 0; j < m; j++) g[i][j] = '0'; //默认为‘0’
//确定十字
for(int i = center - 2; i <= center + 2; i++) {
g[center][i] = '$';
g[i][center] = '$';
}
//越界判断
auto&& isvalid = [=](int posx, int posy) -> bool {
return posx >= 0 && posx < m && posy >= 0 && posy < m;
};
//每次迭代的处理
auto&& made = [&](const char&& ch1, const char&& ch2) {
for(int i = 0; i < m; i++) {
for(int j = 0; j < m; j++) {
if(g[i][j] == '0') {
for(int k = 0; k < 8; k++) {
int nx = i + dirx[k];
int ny = j + diry[k];
if(isvalid(nx, ny) && g[nx][ny] == ch1)
g[i][j] = ch2;
}
}
}
}
};
//进行n次迭代
while(n--) {
made('$', '.');
made('.', '$');
}
//处理边缘小矩阵
for(int i = 0; i < m; i += m - 2)
for(int j = 0; j < m; j += m - 2)
for(int u = 0; u < 2; u++)
for(int v = 0; v < 2; v++)
g[i + u][j + v] = '.';
//打印输出
for(int i = 0; i < m; i++) printf("%s\n", g[i]);
}