幻方构造公式

来源:百度文库 编辑:神马文学网 时间:2024/05/02 15:40:56
奇数阶幻方构造公式
自学考试计算机应用本科毕业论文
作者:顾熙杰
地址: 浙江省象山县定塘中学
邮编: 315728
摘要:本文向大家介绍一种十分 直观方便的奇数阶幻方构造方法,并由此导出了奇数阶幻方构造公式.
关键字:奇数阶幻方 幻方构造 幻方公式
一)斜方格法
幻方的构造历来深受数学家和业余爱好者的喜爱,其中奇数阶幻方构造方法主要有斜排法和跳马法,本人经过一段时间研究,对do la loubere的斜排法作了较大改进,自称为斜方格法,现介绍如下。
以3阶幻方为例:先以自然顺序作中间的3*3主方阵,上下左右各作一个辅助方阵,以主副对角线为准各画3条平行线,连成如下图的斜方格,方格线所在的数字即构成了一个3阶幻方。
用同样方法可以作出任意奇数阶幻方,如下面的5阶幻方。
二)计算机算法
现在给出构造任意奇数阶幻方在Excel上描述的计算机算法,为减少篇幅,次要细节忽略不述,需要者可到本人主页下载代码.
ReDim B(1 - N To 2 * N, 1 - N To 2 * N) As Long
'构造方阵
For I = 1 To N
For J = 1 To N
B(I, J) = (I - 1) * N + J '(1)式 主方阵
B(I - N, J) = B(I, J) '(2)式 辅助方阵
B(I + N, J) =B(I, J) '(3)式 辅助方阵
B(I, J - N) = B(I, J) '(4)式 辅助方阵
B(I, J + N) = B(I, J) '(5)式 辅助方阵
Next J
Next I
'从方阵取数构成幻方
For I = 1 To N
For J = 1 To N
Cells(I, J) = B((I + J - (N + 1) / 2), (I - J + (N + 1) / 2)) '(6)式
Next J
Next I
三)优化算法并导出公式
在(1)式中,我们直接用I,J表示出了主方阵(I,J)格子的值,而(2)(3)(4)(5)实际上是主方阵的拷贝,所以也可以用I,J直接表示辅助方阵中格子的值,现在把(1)(2)(3)(4)(5)统一用主方阵的值来表示.
B(X,Y)=B((X+N) MOD N,(Y+N) MOD N) (7)式
上式表示的意义是(1)(2)(3)(4)(5)的任一格可以用主方阵的对应格表示.考虑到主方阵的下标从1开始,
相当于斜排法在超出左边线时要移到右边线,对(7)式修正如下:
B(X,Y)=B((X+N-1) MOD N+1,(Y+N-1) MOD N+1) (8)式
由于(8)式的右边代表主方阵的格子,所以可以代入(1)式直接求出他的值.
B(X,Y)=((X+N-1) MOD N+1-1)*N+(Y+N-1) MOD N+1 化简得
B(X,Y)=((X+N-1) MOD N)*N+(Y+N-1) MOD N+1 (9)式
令X=(I + J - (N + 1) / 2) ,Y= (I - J + (N + 1) / 2) 由(6)(9)两式得:
Cells(I, J)=(((I + J - (N + 1) / 2)+N-1) MOD N)*N+ ((I - J + (N + 1) / 2)+N-1) MOD N +1 化简得
Cells(I, J)=((I+J+(N-3)/2) MOD N)*N+(I-J+(3*N-1)/2) MOD N+1 (10)式
由于已经消去了辅助空间B(),(10)式 实际上就是我们要寻找的奇数N阶幻方构造公式.对此可以表示为;
N(I,J)=((I+J+(N-3)/2) MOD N)*N+(I-J+(3*N-1)/2) MOD N +1 (11)式
我们把(11)式看成是一个奇数N阶幻方构造函数, 变量 I J 代表了幻方所在的格子坐标,函数N(I,J)代表了在(I,J)格子应该填入的数字.其中 I J 从1到N.
参考文献:Richard A.Brualdi 组合数学 机械工业出版社 2002年1月出版
公式法
程序代码
#include
#include
using namespace std;
int main()
{
int t,i,j;
cin >> t;
for(i=1;i<=t;i++)
for(j=1;j<=t;j++)
{
cout << ((j+i+(t-3)/2) % t)*t+(j-i+(3*t-1)/2) % t +1 << '\t';
if(j==t)
cout << endl;
}
cout << endl;
cin >> t;
system("pause");
return 0;
}
填充法
程序代码
#include
#include
using namespace std;
int a[1000][1000];
int main()
{
int n,t;
cin >> t;
memset(a,0,sizeof(int));
for(int j=0,x=t/2,y=0;j{
a[y][x]=j+1;
if(y>0&&x{
if(!a[y-1][x+1])
{
y--;
x++;
}
else y++;
}
else if(!y)
{
if(x{
if(!a[t-1][x+1])
{
y=t-1;
x++;
}
else
y++;
}
else
{
if(!a[t-1][0])
{
x=0;
y=t-1;
}
else y++;
}
}
else if(x==t-1)
{
if(y>0)
{
if(!a[y-1][0])
{
x=0;
y--;
}
else
y++;
}
else
{
if(!a[t-1][0])
{
x=0;
y=t-1;
}
else y++;
}
}
}
for(int y=0;yfor(int x=0;x{
cout << a[y][x] << '\t';
if(x==t-1)
cout << endl;
}
system("pause");
return 0;
}