神奇的幻方,一道简单的模拟题,一看到题目第一反应是直接按照给出的规则进行就可以了,于是有了如下代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
int N,i,j,count=1,a[40][40]={0};
scanf("%d",&N);
i=1,j=(N+1)/2;
a[i][j]=count;
while(count<N*N)
{
if(i==1&&j!=N)
{
i=N;
j++;
count++;
a[i][j]=count;
continue;
}
if(j==N&&i!=1)
{
i--;
j=1;
count++;
a[i][j]=count;
continue;
}
if(i==1&&j==N)
{
i++;
count++;
a[i][j]=count;
continue;
}
if(!a[i-1][j+1])
{
i--;j++;
count++;
a[i][j]=count;
}
else
{
i++;
count++;
a[i][j]=count;
}
}
for(i=1;i<=N;i++)
{
for(j=1;j<=N;j++)
printf("%d ",a[i][j]);
printf("\n");
}
}
在循环里面通过大量特别判断就可以AC全部,但是有一点要注意,N只能是奇数,如果是偶数的话幻方会出问题,这一点一开始没注意,一直以为是程序的问题!
但这么简单的题目为什么要写出来呢?因为题解里有大佬,把所有规则糅合在一起,每次放在右上方,如果右上有数,就放在正下方。这个规则比题目里给的简单很多,那么究竟是不是对的呢?(不用说也知道肯定是对的)我们通过对比,发现只有当数在右上角时题目所给规则比较特殊,是直接放在正下方,那么我们可以反推,由于数都是从右半部分(以主对角线未区分)左下到右上填进幻方的,因此我们能够断定,右上角填完数后左下角一定有数,因此能够将这条看似特殊的规则统一。
此外还有一个需要注意的地方,就是对于超过了限制的行列该怎么办,肯定是能想到模运算的,但是C中模运算对负数不起作用,因此需要加上N,并且要注意数组中存储的位置是从0还是1开始。AC代码如下(参考题解写出)。
#include<stdio.h>
int n,a[40][40],x,y;
int main(){
scanf("%d",&n);
x=1,y=(n+1)/2;
for(int i=1;i<=n*n;i++){
a[x][y]=i;
if(!a[(x+n)%n+1][y%n+1]) x=(x+n)%n+1,y=y%n+1;
else x=x%n+1;//数学运算
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
}