偶数阶幻方填法.docx
《偶数阶幻方填法.docx》由会员分享,可在线阅读,更多相关《偶数阶幻方填法.docx(19页珍藏版)》请在冰点文库上搜索。
偶数阶幻方填法
偶数阶幻方填法
以4阶为例,说说偶数阶的填法:
首先,按顺序写下16个数:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
接下来固定对角线上数字不动(这里是1、6、11、16和4、7、10、13),其它数字作左右对换,如2与3换,5与8换等,得到下面的排列:
1 3 2 4
8 6 7 5
12 10 11 9
13 15 14 16
继续固定对角线,其他数字作上下对称变换,如8与12换,2与15换等,得到如下排列:
1 15 14 4
12 6 7 9
8 10 11 5
13 3 2 16
这就是四阶幻方,每行每列四个数字之和均为34,其他偶数阶幻方填法可类推!
奇数阶幻方——口诀
1坐边中间,斜着把数填;
出边填对面,遇数往下旋;
出角仅一次,转回下格间。
一、奇数阶纪方的构造方法(楼梯法)。
把1(或最小的数)放在第一行正中;
按以下规律排列剩下的n*n-1个数:
1)每一个数放在前一个数的右上一格;
2)如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;
3)如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;
4)如果这个数所要放的格已经超出了顶行且超出了最右列那么就把它放在前一个数的下一行同一列的格内;
5)如果这个数所要放的格已经有数填入,处理方法同4)。
图示:
* 1 * * 1 *
* * * * * *
* * * * * 2
* 1 * * 1 *
3 * * 3 * *
* * 2 4 * 2
* 1 * * 1 6
3 5 * 3 5 *
4 * 2 4 * 2
* 1 6 8 1 6
3 5 7 3 5 7
4 * 2 4 * 2
8 1 6
3 5 7
4 9 2
奇数阶幻方的一种用公式表达的构造方法:
设x是要填入的数,(xx,yy)是坐标。
坐标如何确定呢?
k=(x-1)divn+(n+3)div2+(x-1)
yy=k-(k-1)divn*n
p=(n+1)div2+(x-1)-(x-1)divn
xx=n+1-p+(p-1)divn*n
二、双偶阶(4k)阶幻方的构造方法。
就是说,阶数可以被4整除。
看看4阶幻方的制作方法:
先把数字,按顺序写(从左到右,从上到下):
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
然后把对角线,换成互补的数字。
定义:
互补:
如果两个数字的和,等于幻方最大数和最小数的和,即n*n+1,称为互补。
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
人们从4阶幻方的制作方法,找到了构造双偶阶幻方的方法:
对于n=4k阶幻方,我们先把数字按顺序填写。
写好后,按4*4把它划分成k*k个方阵。
把每个小方阵的对角线,象制作4阶幻方的方法一样,换成互补的数字,就构成幻方。
事实上,有些小方阵的对角线是连着的。
但是因为没有办法画图,我只能这样子描述。
双偶阶幻方另一种用PASCAL程序语句表达的构造的方法如下:
fori:
=1tondo
forj:
=1tondo
begin
ifjmod4>1thenm:
=1
elsem:
=0;
k:
=n-i-(n-2*i+1)*m;
ifimod4>1thenm:
=1
elsem:
=0;
L:
=n-j+1-(n-2*j+1)*m;
a[i,j]:
=k*N+L;
end;
三、单偶阶(4k+2)幻方的构造
阶数是偶数,但是,又不能被4整除。
这是最难的一种幻方。
一种构造n=4k+2幻方的方法:
(1)先排出4k的双偶阶幻方
(2)根据幻方的性质,每个数都同时加上8k+2
(3)把它扩展成为4k+2的方阵。
这样,四周包围着一圈。
我们只要把
1,2,3……,8k+2,(4k+2)^2,(4k+2)^2-1,……,(4k)^2+1+8k+2
这些数字,填入最外一圈,使得:
对角线两端,每行、每列两端数字互补。
当然,最后圈的两横,两列各数之和要等于变幻常数。
以制作6阶幻方为例:
先制作出4阶幻方。
方阵的每个数字,加上8k+2=10
再把它扩大成6阶,如下图:
* * * * * *
* 26 12 13 23 *
* 15 21 20 18 *
* 19 17 16 22 *
* 14 24 25 11 *
* * * * * *
我们只要把
1,2,3,……,9,10,
36,35,34,……27
填入外圈。
不过,当n较大时,外圈的填法也不太容易。
有一种公式来填外圈。
坐标(j,i)为j行i列的。
先固定填下这10个数:
a[1,1]=1 a[n,1]=4 a[n-1,1]=10 a[2,n]=3 a[3,n]=5 a[4,n]=7
a[n,n-2]=2 a[n,n-1]=9 a[1,2]=6 a[1,3]=8
当n=4k+2时,
a[j,i]=
11,12,…,k+9 (j=1, i=4..k+2)
k+10,k+11,…,2k+8 (j=5..k+3, i=n)
2k+9,2k+10,…,3k+7 (j=n,i=2k+2..3k)
3k+8,3k+9,…,5k+5 (j=2k+3..4k,i=1)
5k+6,5k+7,…,6k+4 (j=n, i=3k+1..4k-1)
6k+5,6k+6,…,7k+3 (j=k+4…2k+2, i=n)
7k+4,7k+5,…,8k+2 (j=1, i=k+3..2k+1)
按公式算出来后,实际上外圈已经填好了一半了。
剩下来的工作,只要把剩下的相对应元素,填下去。
(同行两端的数相对应、同列两端的数相对应、两条对角线两端的数相对应,每对之和为n*n+1)。
介绍另外一种构造单偶阶幻方的方法:
<1>基本图(是个6阶方阵)
42 42 12
13 13 43
42 12 42
13 43 13
42 42 12
13 13 43
这个方阵要把它按2*2把大方阵分割成3*3个格,每个格子里4个数都是1,2,3,4,只是方向上不同。
<2>如果要作的幻方不是6阶,是更大的阶数:
每次同时在最上面、最下面加入下面方阵:
42 42 12
13 13 43
每加一次,多出4行来,直至想要的阶数。
这样加后是个长方形方阵,左边、右边怎么办?
左边都用
43
12
同时,右边都用
12
43
填充,每次多出4列来,直至想要的阶数。
下面是加成10*10方阵的例子:
43 42 42 12 12
12 13 13 43 43
43 42 42 12 12
12 13 13 43 43
43 42 12 42 12
12 13 43 13 43
43 42 42 12 12
12 13 13 43 43
43 42 42 12 12
12 13 13 43 43
如果把每2*2的小格子四个数,看成一个格子,这是一个2k+1奇数阶方阵。
画个(2k+1)*(2k+1)的格子吧,格子画大一点,我们要按奇数阶幻方的填法,填写这些格子,只不过每次要填写的是四个数。
方向跟着制作出来的参考图方向一样。
例:
我们要做一个6阶的幻方。
参考图当然是用<1>基本图,不需要迭加了。
然后,列成3*3个大格子,大格子的顺序我们按奇数幻方的顺序填写,小格子里的顺序按1,2,3,4这四个数字的方向填写,按顺序每次填入4个数:
** 42 ** ** 42 **
** 13 ** ** 13 **
** ** ** ** ** **
** ** ** ** ** **
** ** ** ** ** 56
** ** ** ** ** 87
=============================================
* * 42 ** * * 42 **
* * 13 ** * * 13 **
1210 ** ** 12 10 ** **
9 11 ** ** 9 11 ** **
* * ** 56 1614 ** 56
* * ** 87 1315 ** 87
=============================================
…………
继续直至填完。
三、练习
1、用1、4、7、10、13、16、19、22、25填出三阶幻方。
2、用95、85、75、65、55、45、35、25、15填出三阶幻方。
3、用1—81八十一个自然数填出一个九阶幻方。
4、用1/2、1/3、2/3、1/4、3/4、1/6、1/12、5/12、7/12九个分数摆一个三阶幻方。
奇数阶幻方程序
/**
*n阶幻方程序
*完成者:
meteor135
*完成日期:
2003.9.8
*编译环境:
VC6.0
*/
#include
#include
#include
voidshowFangzhen(intn);
intmain()
{
//输出10组幻方
for(intn=0;n<10;n++)
showFangzhen(2*n+1);
cout<<"Pressentertoquit!
";
cin.get();
return0;
}
voidshowFangzhen(intn)
{
if(!
(n%2))return;
inti,j,**array;
//为指针分配动态内存
array=newint*[n];
for(i=0;i{
array[i]=newint[n];
}
//初始化数组
for(i=0;i{
for(j=0;j{
array[((n-1)/2+i-j+n)%n][(3*n-1+j-2*i)%n]=i*n+j+1;
//or
//array[(n+2*i-j)%n][((n-1)/2+n+j-i)%n]=i*n+j+1;
}
}
//输出n阶幻方
cout<"<for(i=0;i{
for(j=0;j{
cout<}
cout<}
cout<
//释放动态内存
for(i=0;i{
delete[]array[i];//原来是deletearray[i];
}
delete[]array;
}
可能是n阶幻方的程序
这是我的幻方程序,在TC3。
0下通过可以动态显示其中M=n*n+1(n为幻方阶数)?
?
?
?
#include
#include
#include
#defineN3
#defineM226
voidmain()
{textmode(C40);
clrscr();
intx,y,p,q,n,num=1;
inta[M][M];
intflag=0;
intk,s;
for(k=0;k<=M-1;k++)
for(s=0;s<=M-1;s++)
a[k][s]=0;
printf("n=?
");
while(flag==0)
{
scanf("%d",&n);
if(n>=1&&n<=M-1&&n%2!
=0)
flag=1;
// printf("inputerror!
");
}
if(n>7)
// textmode(C80);
clrscr();
gotoxy((n/2+1)*N,N);
printf("%d",num);
x=n/2+1;
y=1;
a[x][y]=num;
num++;
while(num<=n*n)
{
if(p=x,x-1<1)
x=n;
else
x--;
if(q=y,y-1<1)
y=n;
else
y--;
if(a[x][y]==0)
a[x][y]=num;
else
{
a[p][q+1]=num;
x=p;
y=q+1;
}
gotoxy(x*N,y*N);
printf("%d",num);
num++;
delay(300);
}
charch;
ch=getchar();
ch=getchar();
}
任一阶幻方
#include
#include
voidswap(int*a,int*b)
{
intt;
t=*a;
*a=*b;
*b=t;
}
voidhf1(intn,int*p)
{
intm=1,i,j,k,l;
for(i=0;ifor(j=0;j*(p+i*n+j)=0;
for(i=0,j=(n-1)/2;;){
*(p+i*n+j)=m++;
if(m>n*n)
break;
k=i-1;
l=j+1;
if(k==-1)
k=n-1;
if(l==n)
l=0;
if(*(p+k*n+l)!
=0){
i++;
continue;
}
i=k;
j=l;
}
}
voidhf2(intn,int*p)
{
inti,j,*q;
q=malloc(n*n/2);
hf1(n/2,q);
for(i=0;ifor(j=0;j*(p+i*n+j)=*(q+i*n/2+j);
*(p+(i+n/2)*n+j+n/2)=*(p+i*n+j)+n*n/4;
*(p+i*n+j+n/2)=*(p+(i+n/2)*n+j+n/2)+n*n/4;
*(p+(i+n/2)*n+j)=*(p+i*n+j+n/2)+n*n/4;
}
}
for(i=0;ifor(j=0;j<(n/2-1)/2;j++)
swap(p+i*n+j,p+(i+n/2)*n+j);
for(j=n-1;j>=n-(n-4)/4;j--)
swap(p+i*n+j,p+(i+n/2)*n+j);
}
swap(p+(n/2-1)/2*n,p+(3*n/2-1)/2*n);
swap(p+(n/2-1)/2*n+(n/2-1)/2,p+(3*n/2-1)/2*n+(n/2-1)/2);
}
voidhf3(intn,int*p)
{
inti,j,k,m=1;
for(i=0;ifor(j=0;j*(p+i*n+j)=m++;
for(k=0;kfor(i=k,j=0;jif(i==n)
i=0;
swap(p+i*n+j,p+(n-1-i)*n+n-1-j);
}
for(i=k,j=n-1;j>=n/2;i++,j--){
if(i==n)
i=0;
swap(p+i*n+j,p+(n-1-i)*n+n-1-j);
}
}
}
voidmain()
{
inti,j,n,*p;
printf("Entern:
");
scanf("%d",&n);
p=malloc(2*n*n);
if(n%2!
=0)
hf1(n,p);
elseif(n%4!
=0)
hf2(n,p);
else
hf3(n,p);
for(i=0;ifor(j=0;jprintf("%-4d",*(p+i*n+j));
printf("\n\n");
}
}