Input
输入方阵的行 (列) 数
Output
输出魔方阵,每个数据占4位,右对齐
Sample Input
3
Sample Output
8 1 6
3 5 7
4 9 2
结果示意:
是不是看起来很帅的样子
魔方阵固定的求解方法
(1) 1总是位于第一行的中间
(2) 下一个数一般位于前一个数的右上方。如: 上面3*3方阵中的5,在4的右上方
(3)若右上方超过方阵的右边界,则下一个数的填写位置左移到该行最左边(平,行数不变)。如上面3*3方阵中的3,本来应该在2的右上方,现在被平移到了最左过
(4)若右上方超过上边界,则数的填写位置下移到最下边 (列数不变)
如上面方阵中的2,就被下移到了最下面一行
(5)若计算出的位置已经填过数,则下一个数应填写到上一个数的下方。如上面方阵中的4,就被填写到了3的下方
当读完了题意之后在写代码的过程中还发现了该题有一个隐藏条件,就是当其同时超过右边界和上边界的时侯会处于上一个数的下方,比如输出样例中的7。
思路解读
在上述给了题目中数据的关系之后,很容易发现下一个数的位置和上一个数的位置有关系,所以可以用nowx,nowy分别表示目前需要填充的数的行位置以及列位置。用nextx,nexty分别去表示题目中给的填充关系,用nextx,nexty去实现下一个数需要填充的位置。
目前可以写出的伪代码:
nextx=nowx-1;
nexty=nowy+1; //根据第(2)个要求向右上方移动,可以得到next与now之间行列有左边的关系式。
//然后根据nextx,nexty去对题目中给的要求进行下一个数的位置约束
//根据第(3)个要求
if(nexty>=n){
nexty=0;
}
//根据第(4)个要求
if(nextx<0){
nextx=n-1;
}
//根据第(5)个要求
if(a[nextx][nexty]!=0){//不为0也就是下一个要填充的位置是被占据的。
nextx=nowx+1;
nowy=nowy;
}
还有隐藏要求
if(nextx<0&&nexty>=n){
nextx=nowx+1;
nexty=nowy;
}
nowx=nextx;
nowy=nexty;
下面是完整结合之后的代码:其中,要求3、4,以及隐藏要求之间进行结合是需要注意其中的逻辑关系。
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
int a[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
a[i][j]=0;
}
}
int cnt=1;
int nowx=0;//初始化存放1的位置
int nowy=n/2;
int nextx,nexty;
while(cnt<=n*n){
a[nowx][nowy]=cnt++;
// printf("%d",cnt);
nextx=nowx-1;
nexty=nowy+1;
// printf("nowx=%d nowy=%d\n",nowx,nowy);
// printf("next=%d %d\n",nextx,nexty);
if(nextx<0&&nexty>=n){//隐藏条件
nextx=nowx+1;
nexty=nowy;
}else if(nextx<0){//要求4
nextx=n-1;
}else if(nexty>=n){//要求3
nexty=0;
}
if(a[nextx][nexty]!=0){//要求6
nexty=nowy;
nextx=nowx+1;
}
nowx=nextx;
nowy=nexty;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
}