题目:
在n*n的方阵里填入1,2,3,......,n*n ,要求填成蛇形。例如, n = 4时候方阵为:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
上面的方阵中 , 多余的空格是为了便于观察,不必严格输出。n≤ 8 .
分析:
类比着在数学上的矩阵,我们可以用一个二维数组来存题目中的方阵,只需要声明一个二维数组就可以获得一个方阵,在声明时候,二维数组比一定非要是n*n的,也可以声明为m * n的矩阵。
从一开始依此填写。设“笔”的坐标为(x,y),则一开始x = 0 , y = n -1 ,即从第零行第 n-1 列开始,我们用 n = 4 为例子来说,这个“笔”的轨迹是:下 下 下 左 左 左 上 上 上 右 右 下 下 左 上 。总之,先是下到不能填为止,然后是左,再接着是上,最后是右 。 不能填就是再走就会出界的情况(例如 4 -> 5),或者再走再走就要走到前边我们填过的格子,(例如12->13)。如果把所有的格子全都初始化为 0 ,我们就可以方便的加以判断。
下面我们来上代码看看是不是很难以理解:
#include<iostream>
#include<cstdio>
#include<string.h>
#define maxn 20
int a[maxn][maxn];
using namespace std;
int main(){
int n , x , y , tot = 0 ;
scanf("%d",&n);
memset(a , 0 , sizeof(a));
tot = a[x = 0][y = n - 1] = 1 ;
while(tot < n * n){
while(x + 1 < n && !a[x+1][y]) //注意,这里的!a[x+1][y] 等价于a[x+1][y] == 0,这样是简写
a[++x][y] = ++tot ;
while(y - 1 >= 0 && !a[x][y-1])
a[x][--y] = ++tot ;
while(x - 1 >= 0 && !a[x-1][y])
a[--x][y] = ++ tot ;
while(y + 1 < n && !a[x][y+1])
a[x][++y] = ++tot ;
}
for(x = 0 ; x < n ; x ++){
for(y = 0 ; y < n ; y ++){
printf("%3d",a[x][y]);
}
printf("\n");
}
return 0 ;
}
注释:上边的四条while判断语句有点儿让人难以理解,但是他们十分相似,因此我在这里就只介绍其中的一条了:我来介绍第一条while语句吧,不断的往下走,并且开始填数。
我们开始时候的原则还是先开始判断再移动的,而不是发现走不通再回来。这样我们只要预判,也就是判断是不是会越界,以及如果继续走会不会走到我们填过数字的格子了。
越界我们需要判断x+1<n,因为y的值并没有修改,下一个格子是(x+1,y),因此只需要a【x+1】【y】 == 0 也就是我们简写的 !a【x+1】【y】。
可能还有些人会发现这里边有一个潜在的bug 如果越界,x+1 会等于n ,a【x+1】【y】将无法访问,但是不用担心,因为我们在链接的时候用的是 && ,这是个短路运算符 , 也就是说,如果x+1<n为假,我们就不会计算“!a【x+1】【y】”也就是说不会越界!~!!!!