lol怎么快速左右移动:幻方构造公式

来源:百度文库 编辑:偶看新闻 时间:2024/05/01 02:12:54

幻方构造公式

奇数阶幻方构造公式

自学考试计算机应用本科毕业论文
 
作者:顾熙杰
地址: 浙江省象山县定塘中学
邮编: 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;y            for(int x=0;x              {
                 cout << a[y][x] << '\t';
                 if(x==t-1)
                   cout << endl;
              }
    system("pause");
    return 0;
}