Table of Contents
题目
分析
这道题先要分析清楚填写的方向以及方向的转化。
按照题意,填写的方向是:“右-下-左-上-……”的循环,这样的循环直接让我们联想到“模运算”:如果我们用某种方式将这四个方向与0/1/2/3联系起来,就能通过简单的(current_dir + 1) % 4的方式处理转向。
什么时候转向呢?显然是在到了“边界”的时候要转向。注意,这里的“边界”不光是\(n\)确定的四边,还包括“下一个要填写的位置已经被填写了”的约束——这样我们才能逐渐向内收缩。
假定下一个填写的位置是next_x/next_y,这个边界判定就是:
if (next_x < 0 || next_x >= n || next_y < 0 || next_y >= n || x[next_x][next_y] != 0)
出现这个情况时,就要转向。
用两个数组分别代表某个方向上的坐标变化
我们还会看到很多题目,用两个数组表示在某个方向前进时,x/y的变化量:
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
这里我们就解决了“哪个方向”和“x/y如何变化”之间的关联。例如,方向0(向右)的时候,dx[0]=0, dy[0]=1,表明坐标的变化是x不变,y加1。其他以此类推。
一旦发生转向操作,我们先转向,然后更新坐标变化:
if (next_x < 0 || next_x >= n || next_y < 0 || next_y >= n || x[next_x][next_y] != 0)
{
curr_dir = (curr_dir + 1) % 4; // 顺时针转向
next_x = curr_x + dx[curr_dir];
next_y = curr_y + dy[curr_dir];
}
最后,更新当前的坐标以进行下轮操作。
答案

思考
本题有个要求可能被看漏。题目要求:每个数字有都会占用 3 个字符,前面使用空格补齐。因此在输出的时候需要用setw(3)处理。
