一.两个矩阵
1.回型矩阵
描述:给你一个整数n,按要求输出n∗n的回型矩阵。
输入描述:输入一行,包含一个整数n,1<=n<=19。
输出描述:输出n行,每行包含n个正整数。
例如:
输入:4
输出:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
这道题目,其实不难,观察我们可以发现
它是一圈一次循环,也就是说,我们只要写完一圈的代码,然后循环即可。不过还是要注意点细节。
#include<stdio.h> int main() { int n,i,j; int arr[20][20]={0}; scanf("%d",&n); int out=1; int x=0; int y=n-1; while(out<=n*n) { for(i=x;i<=y;i++) arr[x][i]=out++; for(i=x+1;i<=y;i++) arr[i][y]=out++; for(i=y-1;i>=x;i--) arr[y][i]=out++; for(i=y-1;i>x;i--) arr[i][x]=out++; x++; y--; } for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf("%d ",arr[i][j]); } printf("\n"); } return 0; }
对于循环体内的代码端注意要把定量转换为变量。因为它是在不断变换之中的。
结果:
2.蛇形矩阵
描述:给你一个整数n,输出n∗n的蛇形矩阵。
输入描述:输入一行,包含一个整数n
输出描述:输出n行,每行包含n个正整数,通过空格分隔。1<=n<=1000
例如:
输入:
4
输出:
1 2 6 7
3 5 8 13
4 9 12 14
10 11 15 16
可以简单画个图分析一下:
①.暴力求解
通过这个图形,可以直观看到二维数组的变换,但是怎么转换成计算机语言还是比较难办的。笔者在初接触这个题目,是通过坐标直接暴力求解的,但是过于繁琐,也不易于调试,代码可读性较差。不过思路很明确。先见图:
上代码(笔者自己写的比较粗糙,但是万幸跑过去了)虽说比较暴力,但是还是由很多小细节需要注意的。
#include<stdio.h> int main() { int n,i,j; int arr[20][20]={0}; //找坐标关系 scanf("%d",&n); int out=1; int p=1; //第一个没必要讨论 arr[0][0]=out++; arr[n-1][n-1]=n*n; while(p<n)//此处条件还可以写为p<=2*n-2 { for(i=0;i<=p;i++) { arr[i][p-i]=out++; } p++; if(p==n) break; for(i=p;i>=0;i--) { arr[i][p-i]=out++; } p++; } int x=1; while(p<2*n-2) { if(n%2==0) { for(i=p-x;i>=x;i--) { arr[i][p-i]=out++; } p++; x++; if(p==2*n-2) break; for(i=x;i<=p-x;i++) { arr[i][p-i]=out++; } p++; x++; } else { for(i=x;i<=p-x;i++) { arr[i][p-i]=out++; } p++; x++; if(p==2*n-2) break; for(i=p-x;i>=x;i--) { arr[i][p-i]=out++; } p++; x++; } } for(i=0;i<n;i++) { for(j=0;j<n;j++) { printf("%d ",arr[i][j]); } printf("\n"); } return 0; }
算是比较low了,写了有70多行。
②.优化算法(大神确实厉害👍)
如果不从坐标,换个角度思考呢?
为了方便我们从(1,1)开始初始化。
通过上述图片:
我们可以从,移动方向入手,分析发现,它的移动方向只有:
右和右上;
左和左下。
运动情况分为6种:
碰到上边界(即i等于1 且 j小于n): 列增加1,行不变--------往右移动一格
碰到左边界(即j等于1 且 i小于n): 行增加1,列不变--------往下移动一格
碰到右边界(即j等于n): 行增加1,列不变--------往下移动一格
碰到下边界(即i等于n): 列增加1,行不变--------往右移动一格
上面四种是在边界上行走的方式,下面就是在边界中间的运动情况。
除去上面四种的边界情况,就是在边界中间的左下移动
除去上面四种的边界情况,就是在边界中间的右上移动
#include <stdio.h> int array[1001][1001] = { 0 }; int main(void) { int n = 0; scanf("%d",&n); int i = 1, j = 1, k = 0,pos = 1; //pos代表方向移动 1代表右上 -1代表左下 array[i][j] = 1; for (k = 2; k <= n*n; k++) { if (i == 1 && j <n && pos ==1) //碰到上边界,列增加1,行不变 此后行增,列减 { array[i][++j] = k; pos = -1; //方向注意 } else if(j==1 && i<n && pos == -1)//碰到左边界,行增加1,列不变 此后行减,列增 { array[++i][j] = k; pos = 1; //方向注意 } else if (j == n && pos==1) //碰到左边界,行增加1,列不变 此后行增,列减 { array[++i][j] = k; pos = -1; //方向注意 } else if (i == n && pos ==-1) //碰到右边界,列增加1,行不变 此后行减,列增 { array[i][++j] = k; pos = 1; } else if (pos == 1) //除去上面的边界情况,就是中间移动过程 { array[--i][++j] = k; } else if(pos == -1) { array[++i][--j] = k; } } for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) printf("%d ",array[i][j]); printf("\n"); } return 0; }
不得不说,这段代码真的行云流水,大神厉害。
运行结果都是正确的。