的方陣叫魔方。n爲奇數時我們有1種構造方法,叫做“右上方” ,例如下面給出n=3,5,7時
的魔方.
3
8 1 6
3 5 7
4 9 2
5
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
7
30 39 48 1 10 19 28
38 47 7 9 18 27 29
46 6 8 17 26 35 37
5 14 16 25 34 36 45
13 15 24 33 42 44 4
21 23 32 41 43 3 12
22 31 40 49 2 11 20
第1行中間的數總是1,最後1行中間的數是n^2,他的右邊是2,從這三個魔方,你可看出“右
上方”是何意。
由1開始填數,將1放在第0行的中間位置。
將魔方陣想象成上下、左右相接,每次往左上角走一步,會有下列情況:
左上角超出上方邊界,則在最下邊相對應的位置填入下一個數字;
左上角超出左邊邊界,則在最右邊相應的位置填入下一個數字;
如果按上述方法找到的位置已填入數據,則在同一列下一行填入下一個數字。
以3×3魔方陣爲例,說明其填數過程,如圖2所示。
圖2 三階魔方陣的生成過程
由三階魔方陣的生成過程可知,某一位置(x,y)的左上角的位置是(x-1,y-1),如果x-1≥0,不用調整,否則將其調整爲x-1+m;同理,如果y-1≥0,不用調整,否則將其調整爲y-1+m。所以,位置(x,y)的左上角的位置可以用求模的方法獲得,即:
x=(x-1+m)%m
y=(y-1+m)%m
如果所求的位置已經有數據了,將該數據填入同一列下一行的位置。這裏需要注意的是。此時的x和y已經變成之前的上一行上一列了,如果想變回之前位置的下一行同一列,x需要跨越兩行,y需要跨越一列,即:
x=(x+2)%m
y=(y+1)%m
注意:可以考慮使用其他方法生成魔方陣。任何算法都有不同的實現方法,通過採用不同實現方法來重新實現算法,這要比單純學習算法的效果好得多。
#include<stdio.h>
#include<stdlib.h>
#define max 20
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
int a[max][max]={0};
int i,j,x=1,y,m;
scanf("%d",&m);
a[1][(m+1)/2]=1;
y=(m+1)/2;
for(i=2;i<=m*m;i++)
{
if(x-1>0&&y-1>0)
{
x=x-1;
y=y-1;
if(a[x][y]==0)
a[x][y]=i;
else {
x=(x+2)%m;
y=(y+1)%m;
if(x==0) x=x+m;
if(y==0) y=y+m;
a[x][y]=i;
}
continue;
}
if(x-1<=0&&y-1>0)
{
x=x-1+m;
y=y-1;
if(a[x][y]==0)
a[x][y]=i;
else {
x=(x+2)%m;
y=(y+1)%m;
if(x==0) x=x+m;
if(y==0) y=y+m;
a[x][y]=i;
}
continue;
}
if(x-1>0&&y-1<=0)
{
x=x-1;
y=y-1+m;
if(a[x][y]==0)
{a[x][y]=i;}
else {
x=(x+2)%m;
y=(y+1)%m;
if(x==0) x=x+m;
if(y==0) y=y+m;
a[x][y]=i;
}
continue;
}
if(x-1<=0&&y-1<=0)
{
x=x-1+m;
y=y-1+m;
if(a[x][y]==0)
a[x][y]=i;
else {
x=(x+2)%m;
y=(y+1)%m;
if(x==0) x=x+m;
if(y==0) y=y+m;
a[x][y]=i;
}
continue;
}
}
for(i=1;i<=m;i++)
{
for(j=m;j>=1;j--)//這裏要注意一下,我就大意了 結果三次WA 仔細發現才找到結果。
{
printf("%4d",a[i][j]);
}
printf("\n");
}
}
return 0;
}