问题描述 :
在一次数学课上,明明的老师讲了一种非常有趣的方阵,称之为三阶魔方阵。它是一个三行三列,由1、2、3、……8、9,九个数字共同构成,且它每行、每列、两对角线之和均相等,于是一个合法的三阶魔方阵就形成了以下的方阵:
8 1 6
3 5 7
4 9 2
富有钻研精神的明明回家后,马上就对三阶魔方阵进行研究。
他总结出了5条n阶魔方阵的规律(n为奇数),如下:
(1) 将“1”放在第一行(最上面一行)中间一列;
(2) 从“2”开始直到n*n为止各数依次按下列规则存放:每一个数存放的行的行数比前一个数的行数减1,每一个数存放的列的列数比前一个数的列数加1,即前一个数的右上方。
(3) 如果上一数的行数为1,则下一个数的行数为n(指最下面一行);
(4) 当上一个数的列数为n时,下一个数的列数应为1(指最左一列);
(5) 如果按上面规则确定的位置上已有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面。
有了以上的方法,明明就可以轻易地构造出任意的n阶魔方阵。
例如构造3阶魔方阵的过程如下:
先将1放在第一行的中间一列:
放1:(参考规则1)
- 1 *
放2:(参考规则3)
- 1 *
-
- 2
放3:(参考规则4)
- 1 *
3 * * -
- 2
放4:(参考规则5)
- 1 *
3 * *
4 * 2
放5:(参考规则2)
- 1 *
3 5 *
4 * 2
放6:(参考规则2)
- 1 6
3 5 *
4 * 2
放7:(参考规则5)
- 1 6
3 5 7
4 * 2
放8:(参考规则4)
8 1 6
3 5 7
4 * 2
放9:(参考规则3)
8 1 6
3 5 7
4 9 2
但是随着n的不断增大,构建一个n阶魔方阵所花的精力就越多。于是明明就请你帮忙,帮助他用程序来构建n阶魔方阵。
明明的问题可以归结为:给你一个阶数n,请你按照题目中描述的方法,构造出n阶魔方阵。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅包括一个正整数n(1≤n≤19,且n是奇数),表示要构造的魔方阵阶数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。输出时,每组运算结果为n阶魔方阵。每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果后面没有空行。 注:通常,显示屏为标准输出设备。
输入范例 :
5
3
输出范例 :
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
8 1 6
3 5 7
4 9 2
#include<stdio.h>
#include<string.h>
int main(void){
int n;
int arr[20][20]={0};
int current_x,current_y; //当前这个数存放的坐标
int pre_x,pre_y; //上一个数存放的坐标
while(scanf("%d",&n)!=EOF){
current_x=1,current_y=(n+1)/2;
arr[current_x][current_y]=1; //先将1放好
pre_x=current_x,pre_y=current_y;
for(int i=2;i<=n*n;i++){ //剩余放n*n-1个数
current_x=pre_x-1,current_y=pre_y+1;
if(pre_x==1){
current_x=n;
}
if(pre_y==n){
current_y=1;
}
if(arr[current_x][current_y]!=0||(pre_x==1&&pre_y==n)){
current_x=pre_x+1;
current_y=pre_y;
}
arr[current_x][current_y]=i;
pre_x=current_x,pre_y=current_y; //更新上一个数的坐标
}
//输出
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(j!=n){
printf("%d ",arr[i][j]);
}
else{
printf("%d",arr[i][j]);
}
}
printf("\n");
}
printf("\n");
memset(arr,0,sizeof(arr));
}
return 0;
}