题目:
在n*n的方阵填入1,2,3……n*n.最后形成蛇形。例如n=4时的方阵为:其中(n<=8)
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
突然对这个题目感兴趣是某天看到姬加有人问到蛇形数组的问题,然后我找到了这个地址看题目,还参考了这里,我自己做的话,确实是没想到用机器人探路的方法,老想着手工硬编码确定填充下标逻辑,╮( ̄▽ ̄")╭。我个人认为我的方法又比上面提到那个参考连接的做的又稍微好些哦,因为限制了while循环的次数,具体请直接看代码啦。这道题目感觉对数组的下标加强了理解,然后还提出了一个不错的思想,用走迷宫或者探路的方式来填充数组。下次试试Z字形的数组填充。
#include <stdio.h> #include <stdlib.h> int main(void){ int n,i,j,k,value; printf("endter dimension:\n"); scanf("%d",&n); /*基本的检测,好吧,我懒得防 * 试图输入100+的人。。*/ if( n<=0){ fprintf(stderr,"dimension must be positive!\n"); exit(1); }else if( 20<n ){ fprintf(stderr,"(\"▔□▔)个人强烈建议乃不要输入这么大的数字,在普通终端无法整齐打印\n"); } /*霍霍霍,C99的变长数组*/ int arr[n][n]; for(i=0;i<n;++i){ for(j=0;j<n;++j) arr[i][j] = 0; } /****************************************/ /*这里有陷阱,y中-1表示的并非像坐标轴那 */ /* 样的为下,而是上,因为正常的数组是逐 */ /* 行增加行号的!所以并不是down,left,up */ /* right ,应该是 up,left,down,right */ /* 顺时针方向 */ /****************************************/ /* [0][0] -->--right---->[0][n-1] 人 | | | | | up down | | 人 | | | [n-1][0]<----left--<--[n-1][n-1] */ /********************************/ /* 顺时针方向 */ /* down , left , up , right */ /* 0 , 1 , 2 , 3 */ /********************************/ /* int xd[] = {1,0,-1,0}; int yd[] = {0,-1,0,1}; i = 0; j = n-1; k = 0; */ /* 从左下角开始*/ i = n-1; j = 0; k = 2; /********************************/ /* counterclock */ /* left,down,right,up */ /* 0 , 1 , 2 , 3 */ /* k应当选择正确的起始方向的序号*/ /* 比如从右上角开始,则起始方向 */ /* 为左,方向代表号为0 */ /********************************/ int xd[] = {0,1,0,-1}; int yd[] = {-1,0,1,0}; i = 0; j = n-1; k = 0; value = 2; arr[i][j] = 1; while(value <= n*n){ i += xd[k]; j += yd[k]; if( i<n && j<n && 0<=i && 0<=j && (arr[i][j] == 0)) arr[i][j] = value++; else{ i -= xd[k]; j -= yd[k]; k = (k+1)%4; /* 这里的巧妙在于,合理构造xd,yd数组 * 使得刚好按照所选的顺序(顺时针或者 * 逆时针)所需的方向前进。这样就不用 * 继续滚到下一个while循环做无谓的测试 * 了,限制while循环严格循环n^2次。这 * 也就是为什么前面强调起始方向的序号 * k一定要正确。*/ i += xd[k]; j += yd[k]; /*if(!( i<n && j<n && 0<=i && 0<=j && (arr[i][j] == 0))) fprintf(stderr,"Impossible\n"); // used for debug */ arr[i][j] = value++; } } /*打印出数组*/ for(i=0;i<n;++i){ for(j=0;j<n;++j){ if( n<10 ) printf("%2d ",arr[i][j]); else printf("%3d ",arr[i][j]); /*大于等于10的时候会出现三位数,故以3位补齐*/ } printf("\n"); } return 0; }
顺便啦,Z形的数组问题:
int main(void){ int n,i,j,k,value,ti; printf("enter array dimension:\n"); scanf("%d",&n); /*霍霍霍,C99的变长数组*/ int arr[n][n]; for(i=0;i<n;++i){ for(j=0;j<n;++j) arr[i][j] = 0; } /* 坐标的规律为 (0,0) * (1,0)(0,1) * (2,0)(1,1)(0,2) * (3,0)(2,1)(1,2)(0,3)...*/ /*真正的算法开始了*/ value = 2; arr[0][0] = 1; while( value <= n*(n-1)/2 ){ for(i=1;i<=n-1;++i){ ti = i; for(j=0;j<=i;++j){ arr[ti--][j] = value++; } } } /*打印数组*/ /*每行长度从n逐渐递减至1*/ for(i=0,k=n;i<n;++i){ for(j=0;j<k;++j){ printf("%2d ",arr[i][j]); } --k; printf("\n"); } return 0; }





