Loading

幻方(附加生成五十阶以内幻方小程序)


 

有时又称魔方(该称呼现一般指立方体的魔术方块)或纵横图,由一组排放在正方形中的整数组成,其每行、每列以及两条对角线上的数之和均相等。通常幻方由从1到N2的连续整数组成,其中N为正方形的行或列的数目。因此N阶幻方有N行N列,并且所填充的数为从1到N2


幻方可以使用N阶方阵来表示,方阵的每行、每列以及两条对角线的和都等于常数M2(N),如果填充数为1,2,3.....,N2,那么有M_{2}(N)={\frac  {N(N^{2}+1)}{2}}


构造法:


  根据构造方法的不同,幻方可以分成三类:奇数阶幻方、 4M阶幻方和 4M+2阶幻方,其中 M为自然数, 2阶幻方不存在。幻方构造法主要有:连续摆数法、阶梯法(楼梯法)、奇偶数分开的菱形法、对称法、对角线法、比例放大法、斯特雷奇法、LUX法、拉伊尔法(基方、根方合成法)、镶边法、相乘法、幻方模式等。


奇数阶幻方构造法


Siamese方法(Kraitchik 1942年,pp. 148-149)是构造奇数阶幻方的一种方法,说明如下:


  • 1放置在第一行的中间。
  • 顺序将2,3,......数放在右上方格中。
  • 当右上方格出界的时候,则由另一边进入。
  • 当右上方格中已经填有数,则把数填入正下方的方格中。
  • 按照以上步骤直到填写完所有N2个方格。

(由于幻方的对称性,也可以把右上改为右下、左上以及左下等方位)


以下图5阶幻方为例,1填写在(1,3)(第一行第三列)的位置上;2应当填写在其右上方格即(0,4)中,由于(0,4)超出顶边界,所以从最底行进入,即(5,4)3填写在(5,4)的右上方格(4,5)中;4填写在(4,5)的右上方格(3,6)中,


由于(3,6)超出右边界,所以从最左列进入,即(3,1)5填写在(3,1)的右上方格(2,2)中;6应该填写的方格(1,3)已经被1所占据,因此填写在(2,2)的正下方格(3,2)中;按照上面的步骤直到所有数填入。


{\begin{bmatrix}8&1&6\\3&5&7\\4&9&2\\\end{bmatrix}} {\begin{bmatrix}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\end{bmatrix}} {\begin{bmatrix}37&48&59&70&81&2&13&24&35\\36&38&49&60&71&73&3&14&25\\26&28&39&50&61&72&74&4&15\\16&27&29&40&51&62&64&75&5\\6&17&19&30&41&52&63&65&76\\77&7&18&20&31&42&53&55&66\\67&78&8&10&21&32&43&54&56\\57&68&79&9&11&22&33&44&46\\47&58&69&80&1&12&23&34&45\end{bmatrix}}
3 5 9

魔方阵不是唯一的,比如5阶魔方阵还可以是:


{\begin{bmatrix}15&6&19&2&23\\16&12&25&8&4\\9&5&13&21&17\\22&18&1&14&10\\3&24&7&20&11\end{bmatrix}}
5

偶数阶幻方构造法


4M阶幻方构造法


对于4M阶幻方一般都用对调法,制作起来很容易。如4阶幻方的排列法:
{\begin{bmatrix}1&2&3&4\\5&6&7&8\\9&10&11&12\\13&14&15&16\end{bmatrix}}
按如上图排列好,再将非主副对角线上的各个数关于中心对调,即成下图:
{\begin{bmatrix}1&15&14&4\\12&6&7&9\\8&10&11&5\\13&3&2&16\end{bmatrix}}


4M+2阶幻方构造法


加边法

6阶为例子,先排出4阶的幻方,如上图,再将图中每一个数都加上8m+2=10,有下图:
{\begin{bmatrix}11&25&24&14\\22&16&17&19\\18&20&21&15\\23&13&12&26\end{bmatrix}}


结果如下:
{\begin{bmatrix}1&9&34&33&32&2\\6&11&25&24&14&31\\10&22&16&17&19&27\\30&18&20&21&15&7\\29&23&13&12&26&8\\35&28&3&4&5&36\end{bmatrix}}


LUX法

在(4M+2)×(4M+2)个方格的适当格点上,先排出2M+1阶的幻方。在前M+1行的格点,全部标上“L”;在第M+1行的中间格点标上“U”,其余格点标上“L”;在第M+2行的中间格点标上“L”,其余格点标上“U”;在余下的M-1行的格点全部标上“X”。将格点上的数乘以4再减4,再按下面的规则加上1至4其中一个数,填入对应的格上:


 4 1    1 4    1 4
  L      U      X
 2 3    2 3    3 2

例子:


[ 68  65  96  93   4   1  32  29  60  57 ]
   17L     24L      1L      8L     15L
[ 66  67  94  95   2   3  30  31  58  59 ]

[ 92  89  20  17  28  25  56  53  64  61 ]
   23L      5L      7L     14L     16L
[ 90  91  18  19  26  27  54  55  62  63 ]

[ 16  13  24  21  49  52  80  77  88  85 ]
    4L      6L     13U     20L     22L
[ 14  15  22  23  50  51  78  79  86  87 ]

[ 37  40  45  48  76  73  81  84  9   12 ]
   10U     12U     19L     21U      3U
[ 38  39  46  47  74  75  82  83  10  11 ]

[ 41  44  69  72  97  100  5  8   33  36 ]
   11X     18X     25X      2X      9X
[ 43  42  71  70  99  98   7  6   35  34 ]
附上我写的一个生成50阶以内幻方的程序(其实二十阶以上就已经没什么意义了....):
 
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef unsigned long long ull;
 5 #define INF 0x3f3f3f3f
 6 const ll MAXN = 1e2 + 7;
 7 const ll MOD = 1e9 + 7;
 8 const double pi = acos(-1);
 9 int Matrix[50][50];
10 int t[50][50];
11 int n;
12 void Move_pos(int &x, int &y, int a[][50], int m) //奇数阶构造移动类二维指针函数
13 {                                                 //这里的奇数阶幻方构造方法是向右上填数字
14     int tx = x, ty = y;
15     x--, y++;
16     if (x == 0)
17         x += m;
18     if (y == m + 1)
19         y -= m;
20     if (a[x][y])
21         x = tx + 1, y = ty;
22 }
23 void pri_Mat()
24 {
25     for (int i = 1; i <= n; i++)
26     {
27         for (int j = 1; j <= n; j++)
28             printf("%-4d ", Matrix[i][j]);
29         printf("\n");
30     }
31 }
32 void Siamese(int a[][50], int m)
33 {
34     int pos_x = 1, pos_y = m / 2 + 1; //1在幻方中的位置
35     int cnt = 1;                      //cnt为要填的数,初始为1
36     a[pos_x][pos_y] = cnt++;
37     while (cnt <= m * m) //m阶幻方要填m*m个数
38     {
39         Move_pos(pos_x, pos_y, a, m);
40         a[pos_x][pos_y] = cnt++;
41     }
42 }
43 int main()
44 {
45     memset(Matrix, 0, sizeof(Matrix));
46     memset(t, 0, sizeof(t));
47     printf("请输入要形成的幻方阶数:");
48     scanf("%d", &n);
49     if (n % 2) //奇数阶构造法(Siamese方法)
50         Siamese(Matrix, n);
51     else if (n % 4 == 0)
52     {
53         for (int i = 1; i <= n; i++)
54             for (int j = 1; j <= n; j++)
55                 Matrix[i][j] = (i - 1) * n + j;
56         for (int i = 1; i < n / 2; i++)
57             for (int j = i + 1; j <= n - i; j++)
58                 swap(Matrix[i][j], Matrix[n + 1 - i][n + 1 - j]);
59         for (int i = 2; i <= n - 1; i++)
60             for (int j = 1; j <= (i <= n / 2 ? i - 1 : n / 2 - i + 3); j++)
61                 swap(Matrix[i][j], Matrix[n + 1 - i][n + 1 - j]);
62     }
63     else
64     {
65         //lux构造4M+2幻方
66         int m = n / 2;
67         Siamese(t, m);
68         for (int i = 1; i <= m; i++)
69             for (int j = 1; j <= m; j++)
70             {
71                 Matrix[2 * i - 1][2 * j - 1] = 4 * t[i][j];
72                 Matrix[2 * i - 1][2 * j] = 4 * t[i][j] - 3;
73                 Matrix[2 * i][2 * j - 1] = 4 * t[i][j] - 2;
74                 Matrix[2 * i][2 * j] = 4 * t[i][j] - 1;
75                 if ((i>m/2+2)||(i == m / 2 + 2 && j != m / 2 + 1) || ((i == m / 2 + 1) && (j == m / 2 + 1)))
76                     swap(Matrix[2 * i - 1][2 * j - 1], Matrix[2 * i - 1][2 * j]);
77                 if (i == m)
78                     swap(Matrix[2 * i][2 * j - 1], Matrix[2 * i][2 * j]);
79             }
80     }
81     pri_Mat();
82     return 0;
83 }


posted @ 2019-04-30 20:13  GrayKido  阅读(2097)  评论(0编辑  收藏  举报