小明玩一个数字游戏,取个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
25
数据范围及提示 Data Size & Hint
无
思路:对于这题,刚开始我是想用数学公式来表示每一个点的计算方法,但是经过复杂的计算后,我放弃了,点太多而且很难表达,所以我就纯粹地模拟了一下
光讲思路没有用,还是要举个栗子(7*7的矩阵):
我用了四个for循环,从外往内标记数组,分别为下、左、上、右,这样经过一轮下来就是一个框了,外面再用一个循环来控制框的数量,就可以完整地把矩阵标记完全
所以这题关键就是要考虑的就是四个for循环的气质条件和循环次数,为了方便,我用了一个flag记录框的层数,最外层是第一层(flag=1),temp来控制框的数量(循环的数量):temp=(n-1)/2
如图所示,我先对这个矩阵做了一些处理,也就是把每一个框的起点先标记好:
如图所示,红色的线标记出来了下左上右的循环起止点,这样就可以嵌套成为一个完整的框了:
那么该怎样确定循环的起止点呢?这里就要用到前面的flag层数了,仔细观察可以发现:
第一个for循环j的起点=n-flag-1,终止点为flag-1;
第二个for循环i的起点=n-flag-1,终止点为flag-1;
第三个for循环j的起点=flag,终止点为n-flag;
第四个for循环的起点=flag,终止点为n-flag-1。
每次a[i][j]都赋值为前面的数+1即可,用一个temp来控制框的数量,每次temp--就可以啦
最后计算对角线的和,这里没什么好说的了,记得最后要减去一个重复的1
代码如下:
1 #include <stdio.h> 2 int main() 3 { 4 int n,i,j;//i表示行,j表示列 5 int a[101][101]={0}; 6 int kk=1;//用来计算奇数的平方 7 int flag=1,temp;//flag记录循环的层数,temp控制循环终止条件 8 int ans=0;//记录两条对角线的和 9 scanf("%d",&n); 10 temp=(n-1)/2; 11 a[(n-1)/2][(n-1)/2]=1;//最中间标记为1 12 for(i=(n-1)/2;i<n;i++)//放入循环开始点 13 { 14 a[i][i]=kk*kk; 15 kk+=2; 16 } 17 while(temp>0)//循环填入边框 18 { 19 for(j=n-flag-1;j>=flag-1;j--)//下 20 { 21 a[n-flag][j]=a[n-flag][j+1]-1; 22 } 23 for(i=n-flag-1;i>=flag-1;i--)//左 24 { 25 a[i][flag-1]=a[i+1][flag-1]-1; 26 } 27 for(j=flag;j<=n-flag;j++)//上 28 { 29 a[flag-1][j]=a[flag-1][j-1]-1; 30 } 31 for(i=flag;i<=n-flag-1;i++)//右 32 { 33 a[i][n-flag]=a[i-1][n-flag]-1; 34 } 35 flag++;//进入下一层 36 temp--;//循环次数减少 37 } 38 for(i=0;i<n;i++)//输出矩阵 39 { 40 for(j=0;j<n;j++) 41 { 42 printf("%d ",a[i][j]); 43 } 44 printf(" "); 45 } 46 /*====================*///计算两条对角线的和 47 for(i=0;i<n;i++) 48 { 49 ans+=a[i][i]; 50 } 51 for(i=n-1;i>=0;i--) 52 { 53 ans+=a[n-1-i][i]; 54 } 55 printf("%d ",ans-1);//因为两条对角线都重复加了矩阵中心的1,所以要减去一个 56 return 0; 57 }