蛇形填空是等考常考题型,通常是从某点出发,由内至外、或由外之内,或顺时针,或逆时针,依次填充。我们来看由内至外这个示例:
示例:
描述:
小明玩一个数字游戏,取个n行n列数字矩阵(其中n为不超过100的奇数),数字的填补方法为:在矩阵中心从1开始以逆时针方向绕行,逐圈扩大,直到n行n列填满数字,请输出该n行n列正方形矩阵。
输入:n(即n行n列)
输出:n+1行,n行为组成的矩阵。
样例输入:3
样例样输出:
5 4 3
6 1 2
7 8 9
分析:
(1)方向设置
蛇形填空需要向下走、向左走、向上走和向右走四个方向。设某点坐标 (x,y),若:
向下走,其坐标为:(x+1,y)
向左走,其坐标为:(x,y-1)
向上走,其坐标为:(x-1,y)
向右走,其坐标为:(x,y+1)
(2)边界判断
方阵左上角的坐标为(0,0),右下角的坐标为(n-1,n-1),故此,
向下走:x+1 < n
向左走:y-1 >= 0
向上走:x-1 >= 0
向右走:y+1 < n
(3)标记填充状态
无论沿哪个方向进行填充,一个是要判断是否越界,另一个就是要判断是否填充过,如果填充过了,就不再填充了。方法就是初始化二维数组为0,0表示未填充,不是0表示已填充过。
从这个例子看,我们摒弃从内向外填充思想,依旧采用由外向内填充,起始点为(n-1,n-1),然后顺时针(左、上、右、下)依次填充。填充最大值,即起始点为n*n,逐一减一,直到中心点为1。实际上,就是将蛇形填空 I 中的代码修改一下起始点,tot由自增1,改为自减1,循环条件由 while(tot<n*n) 改为 while(tot > 1),以及填充方向。
C语言代码如下:
#include <stdio.h>
#define N 100
int main()
{
int x,y,n,a[N][N]={0},tot;
scanf("%d",&n);
x=n-1;
y=n-1;
a[x][y]=n*n;
tot=n*n;
while(tot>1)
{
while(y-1>=0 && a[x][y-1]==0) //向左走
{
y--;
tot--;
a[x][y]=tot;
}
while(x-1>=0 && a[x-1][y]==0) //向上走
{
x--;
tot--;
a[x][y]=tot;
}
while(y+1<n && a[x][y+1]==0) //向右走
{
y++;
tot--;
a[x][y]=tot;
}
while(x+1<n && a[x+1][y]==0) //向下走
{
x++;
tot--;
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;
}
python语言代码如下:
n = int(input())
# 初始化二维数组,这里用list实现,也可以用numpy下的array实现
lst = []
for i in range(n):
l1 = [0] * n
lst.append(l1)
x = n - 1
y = n - 1
tot = lst[x][y] = n * n
while tot > 1:
while y - 1 >= 0 and lst[x][y - 1] == 0: # 向左走
y = y - 1
tot = tot - 1
lst[x][y] = tot
while x - 1 >= 0 and lst[x - 1][y] == 0: # 向上走
x = x - 1
tot = tot - 1
lst[x][y] = tot
while y + 1 < n and lst[x][y + 1] == 0: # 向右走
y = y + 1
tot = tot - 1
lst[x][y] = tot
while x + 1 < n and lst[x + 1][y] == 0: # 向下走
x = x + 1
tot = tot - 1
lst[x][y] = tot
for i in range(n):
for j in range(n):
print(lst[i][j], end=' ')
print()