有时又称魔方(该称呼现一般指立方体的魔术方块)或纵横图,由一组排放在正方形中的整数组成,其每行、每列以及两条对角线上的数之和均相等。通常幻方由从1到N2的连续整数组成,其中N为正方形的行或列的数目。因此N阶幻方有N行N列,并且所填充的数为从1到N2。
幻方可以使用N阶方阵来表示,方阵的每行、每列以及两条对角线的和都等于常数M2(N),如果填充数为1,2,3.....,N2,那么有
构造法:
根据构造方法的不同,幻方可以分成三类:奇数阶幻方、 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)中;按照上面的步骤直到所有数填入。
阶
阶
阶
魔方阵不是唯一的,比如5阶魔方阵还可以是:
阶
偶数阶幻方构造法
4M阶幻方构造法
对于4M阶幻方一般都用对调法,制作起来很容易。如4阶幻方的排列法:
按如上图排列好,再将非主副对角线上的各个数关于中心对调,即成下图:
4M+2阶幻方构造法
加边法
以6阶为例子,先排出4阶的幻方,如上图,再将图中每一个数都加上8m+2=10,有下图:
结果如下:
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
2 using namespacestd;3 typedef long longll;4 typedef unsigned long longull;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 intn;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 voidpri_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], intm)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 intmain()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 }