轴心双对称型同心幻方镶边法构造方法及代码
如果一个n阶的幻方,逐层地剥掉外圈,留下来的方阵仍然是一个个幻方,这个幻方就叫同心幻方,又叫嵌套幻方。
上图中n=7,有3层幻方,最外层幻和为175,中间层和为125,内层和为75.
如果幻方对角线两端的数之和,边上关于横向中间线轴对称的两数之和,关于纵向中间线轴对称的两数之和都相等,则称之为轴心双对称型幻方,这个和为n*n+1,其中一个数为另一个的补数。
上图中n=8,对称两格有定和65,如6+59=7+58=1+64=9+56=18+47=23+42=15+50……=65,你找找看有哪些两数和为65.
构选同心幻方,可以用镶边法。利用补数,从外到内先镶边后加入核心块,根据图示,分奇偶构造同心幻方。
一、奇阶同心幻方构造法
以n=7为例,如图。先按序填写红色的数,每边上个数相同。然后根据互补两数和为50,填写黑色的数。比如1下方的为49,10对角为40.
再接着填写内层红色的数,与上步的顺序一致,但不是从1开始,而是接着上下步最大的红色的数。依次一直做到最内层为3阶为止。
用罗伯法填写最内层3阶幻方。注意,它是边值也是关于中心对称的,不同于外层的关于轴对称。这样就完成了奇阶同心幻方的填写。
C++ 主要代码如下:
#include
int arr[20][20]
= { 0 };
//构造奇数阶幻方的外边:v为内层相对于最外层偏移量,s为开始值,q为相补两数之和
void odd(
const int n, const int v, const int s, const int q)
{
int k
=
n /
2;
int val
=
s;
arr[v][1
+ v] = val;
arr[n -
1 +
v][1
+ v]
= q -
val++;
int i =
0;
for (i = 0; i
< k; i++)
{
arr[k + 1 + i
+ v][v]
= val;
arr[k + 1 + i
+ v][n -
1 +
v]
= q -
val++;
}
for (i = 0; i
< k - 1; i++)
{
arr[v][2 + i
+ v] = val;
arr[n -
1 +
v][2 + i
+ v]
= q -
val++;
}
for (i = 0; i
< k; i++)
{
arr[1 + i
+ v][n -
1 +
v] = val;
arr[1 + i
+ v][v]
= q -
val++;
}
for (i = 0; i
< k; i++)
{
arr[n -
1 +
v][n -
1 - i +
v] = val;
arr[v][n -
1 - i +
v]
= q -
val++;
}
arr[v][v]
= q -
arr[
n - 1
+
v][n -
1 +
v];//左上角
arr[v][n -
1 +
v]
= q -
arr[
n - 1
+
v][v];//改写右上角
}
void oddorder(
int n)
{
int k
=
n / 2 -
1;
//层数
for (
int h = 0; h
< k; h++)
{
odd(n -
h * 2, h, 2 * h * (
n - h) +
1,
n *
n +
1);
}
lao_bo(3, k,
(n *
n - 7) /
2);
//罗伯法
}
}
n=11时的输出:
二、偶阶同心幻方构造法
1.双偶数阶幻方,以n=8为例:
n=16时:
2.单偶数阶幻方,以n=10为例:
n=6时:
这两种总是交替的,8阶是双偶,内层6阶就是单偶。核心处是4阶幻方,用对角线法填写。
C++ 主要代码如下:
//单偶数阶镶边
void even1(
const int n, const int v, const int s, const int q)
{
int k
=
n /
4;
int val
=
s;
int i =
0;
for (i = 0; i
< k; i++)
{
arr[v][2 + i * 4
+ v] = val;
arr[n -
1 +
v][2 + i * 4
+ v]
= q -
val++;
arr[v][3 + i * 4
+ v] = val;
arr[n -
1 +
v][3 + i * 4
+ v]
= q -
val++;
arr[n -
1 +
v][4 + i * 4
+ v] = val;
arr[v][4 + i * 4
+ v]
= q -
val++;
arr[n -
1 +
v][5 + i * 4
+ v] = val;
arr[v][5 + i * 4
+ v]
= q -
val++;
}
arr[v][v]
= q -
arr[
n - 1
+
v][n -
1 +
v];//左上角
arr[n -
1 +
v][v] =
val;//左下角
arr[v][n -
1 +
v]
= q -
val++;
//右上角
for (i = 0; i
< k; i++)
{
arr[1 + i * 4
+ v][n -
1 +
v] = val;
arr[1 + i * 4
+ v][v]
= q -
val++;
arr[2 + i * 4
+ v][v]
= val;
arr[2 + i * 4
+ v][n -
1 +
v]
= q -
val++;
arr[3 + i * 4
+ v][v]
= val;
arr[3 + i * 4
+ v][n -
1 +
v]
= q -
val++;
arr[4 + i * 4
+ v][n -
1 +
v] = val;
arr[4 + i * 4
+ v][v]
= q -
val++;
}
arr[v][1
+ v] = val -
1;
arr[n -
1 +
v][1
+ v]
= q -
(val - 1);
arr[n -
2 +
v][n -
1 +
v] = val;
arr[n -
2 +
v][v]
= q -
val;
}
//双偶数阶镶边
void even2(
const int n, const int v, const int s, const int q)
{
int k
=
n / 4 -
1;
int val
=
s;
int i =
0;
for (i = 0; i
< k; i++)
{
arr[v][2 + i * 4
+ v] = val;
arr[n -
1 +
v][2 + i * 4
+ v]
= q -
val++;
arr[n -
1 +
v][3 + i * 4
+ v] = val;
arr[v][3 + i * 4
+ v]
= q -
val++;
arr[n -
1 +
v][4 + i * 4
+ v] = val;
arr[v][4 + i * 4
+ v]
= q -
val++;
arr[v][5 + i * 4
+ v] = val;
arr[n -
1 +
v][5 + i * 4
+ v]
= q -
val++;
}
arr[v][n -
2 +
v] = val;
arr[n -
1 +
v][n -
2 +
v]
= q -
val++;
arr[n -
1 +
v][n -
1 +
v] = val;//右下角
arr[v][v]
= q -
val++;
//左上角
arr[n -
1 +
v][v] =
val;//左下角
arr[v][n -
1 +
v]
= q -
val++;
//右上角
arr[v][1
+ v] = val;
arr[n -
1 +
v][1
+ v]
= q -
val++;
for (i = 0; i
< k; i++)
{
arr[1 + i * 4
+ v][v]
= val;
arr[1 + i * 4
+ v][n -
1 +
v]
= q -
val++;
arr[2 + i * 4
+ v][n -
1 +
v] = val;
arr[2 + i * 4
+ v][v]
= q -
val++;
arr[3 + i * 4
+ v][n -
1 +
v] = val;
arr[3 + i * 4
+ v][v]
= q -
val++;
arr[4 + i * 4
+ v][v]
= val;
arr[4 + i * 4
+ v][n -
1 +
v]
= q -
val++;
}
arr[n -
3 +
v][v] =
val;
arr[n -
3 +
v][n -
1 +
v]
= q -
val++;
arr[n -
2 +
v][n -
1 +
v] = val;
arr[n -
2 +
v][v]
= q -
val++;
}
//构造偶数阶同心幻方
void evenorder(
int n)
{
int k
=
n / 2 -
2;
//层数
for (
int h = 0; h
< k; h++)
{
int nn
=
n - h *
2;
if (nn % 4 ==
0)even2(nn, h, 2 * h * (
n - h) +
1,
n *
n +
1);
else even1(nn,
h, 2 * h * (
n - h) +
1,
n *
n +
1);
}
hai_er(4, k,
(n *
n - 16) /
2);
//对角线法填写4阶幻方
}
N=20时的输出:
参考:
1. 最简奇阶幻方镶边法(再简化)
- 知乎 (zhihu.com)
2. 构造镶边幻方的代码法
- 百度文库
同心幻方
轴心双对称型同心幻方镶边法构造方法及代码
如果一个n阶的幻方,逐层地剥掉外圈,留下来的方阵仍然是一个个幻方,这个幻方就叫同心幻方,又叫嵌套幻方。
上图中n=7,有3层幻方,最外层幻和为175,中间层和为125,内层和为75.
如果幻方对角线两端的数之和,边上关于横向中间线轴对称的两数之和,关于纵向中间线轴对称的两数之和都相等,则称之为轴心双对称型幻方,这个和为n*n+1,其中一个数为另一个的补数。
上图中n=8,对称两格有定和65,如6+59=7+58=1+64=9+56=18+47=23+42=15+50……=65,你找找看有哪些两数和为65.
构选同心幻方,可以用镶边法。利用补数,从外到内先镶边后加入核心块,根据图示,分奇偶构造同心幻方。
一、奇阶同心幻方构造法
以n=7为例,如图。先按序填写红色的数,每边上个数相同。然后根据互补两数和为50,填写黑色的数。比如1下方的为49,10对角为40.
再接着填写内层红色的数,与上步的顺序一致,但不是从1开始,而是接着上下步最大的红色的数。依次一直做到最内层为3阶为止。
用罗伯法填写最内层3阶幻方。注意,它是边值也是关于中心对称的,不同于外层的关于轴对称。这样就完成了奇阶同心幻方的填写。
C++ 主要代码如下:
#include
int arr[20][20] = { 0 };
//构造奇数阶幻方的外边:v为内层相对于最外层偏移量,s为开始值,q为相补两数之和
void odd(
const int n, const int v, const int s, const int q)
{
int k =
n / 2;
int val =
s;
arr[v][1 + v] = val;
arr[n - 1 +
v][1 + v] = q - val++;
int i = 0;
for (i = 0; i < k; i++)
{
arr[k + 1 + i + v][v] = val;
arr[k + 1 + i + v][n - 1 +
v] = q - val++;
}
for (i = 0; i < k - 1; i++)
{
arr[v][2 + i + v] = val;
arr[n - 1 +
v][2 + i + v] = q - val++;
}
for (i = 0; i < k; i++)
{
arr[1 + i + v][n - 1 +
v] = val;
arr[1 + i + v][v] = q - val++;
}
for (i = 0; i < k; i++)
{
arr[n - 1 +
v][n - 1 - i +
v] = val;
arr[v][n - 1 - i +
v] = q - val++;
}
arr[v][v] = q - arr[
n - 1 +
v][n - 1 +
v];//左上角
arr[v][n - 1 +
v] = q - arr[
n - 1 +
v][v];//改写右上角
}
void oddorder(
int n)
{
int k =
n / 2 - 1;
//层数
for (
int h = 0; h < k; h++)
{
odd(n - h * 2, h, 2 * h * (
n - h) + 1,
n *
n + 1);
}
lao_bo(3, k, (n *
n - 7) / 2);
//罗伯法
}
}
n=11时的输出:
二、偶阶同心幻方构造法
1.双偶数阶幻方,以n=8为例:
n=16时:
2.单偶数阶幻方,以n=10为例:
n=6时:
这两种总是交替的,8阶是双偶,内层6阶就是单偶。核心处是4阶幻方,用对角线法填写。
C++ 主要代码如下:
//单偶数阶镶边
void even1(
const int n, const int v, const int s, const int q)
{
int k =
n / 4;
int val =
s;
int i = 0;
for (i = 0; i < k; i++)
{
arr[v][2 + i * 4 + v] = val;
arr[n - 1 +
v][2 + i * 4 + v] = q - val++;
arr[v][3 + i * 4 + v] = val;
arr[n - 1 +
v][3 + i * 4 + v] = q - val++;
arr[n - 1 +
v][4 + i * 4 + v] = val;
arr[v][4 + i * 4 + v] = q - val++;
arr[n - 1 +
v][5 + i * 4 + v] = val;
arr[v][5 + i * 4 + v] = q - val++;
}
arr[v][v] = q - arr[
n - 1 +
v][n - 1 +
v];//左上角
arr[n - 1 +
v][v] = val;//左下角
arr[v][n - 1 +
v] = q - val++;
//右上角
for (i = 0; i < k; i++)
{
arr[1 + i * 4 + v][n - 1 +
v] = val;
arr[1 + i * 4 + v][v] = q - val++;
arr[2 + i * 4 + v][v] = val;
arr[2 + i * 4 + v][n - 1 +
v] = q - val++;
arr[3 + i * 4 + v][v] = val;
arr[3 + i * 4 + v][n - 1 +
v] = q - val++;
arr[4 + i * 4 + v][n - 1 +
v] = val;
arr[4 + i * 4 + v][v] = q - val++;
}
arr[v][1 + v] = val - 1;
arr[n - 1 +
v][1 + v] = q - (val - 1);
arr[n - 2 +
v][n - 1 +
v] = val;
arr[n - 2 +
v][v] = q - val;
}
//双偶数阶镶边
void even2(
const int n, const int v, const int s, const int q)
{
int k =
n / 4 - 1;
int val =
s;
int i = 0;
for (i = 0; i < k; i++)
{
arr[v][2 + i * 4 + v] = val;
arr[n - 1 +
v][2 + i * 4 + v] = q - val++;
arr[n - 1 +
v][3 + i * 4 + v] = val;
arr[v][3 + i * 4 + v] = q - val++;
arr[n - 1 +
v][4 + i * 4 + v] = val;
arr[v][4 + i * 4 + v] = q - val++;
arr[v][5 + i * 4 + v] = val;
arr[n - 1 +
v][5 + i * 4 + v] = q - val++;
}
arr[v][n - 2 +
v] = val;
arr[n - 1 +
v][n - 2 +
v] = q - val++;
arr[n - 1 +
v][n - 1 +
v] = val;//右下角
arr[v][v] = q - val++;
//左上角
arr[n - 1 +
v][v] = val;//左下角
arr[v][n - 1 +
v] = q - val++;
//右上角
arr[v][1 + v] = val;
arr[n - 1 +
v][1 + v] = q - val++;
for (i = 0; i < k; i++)
{
arr[1 + i * 4 + v][v] = val;
arr[1 + i * 4 + v][n - 1 +
v] = q - val++;
arr[2 + i * 4 + v][n - 1 +
v] = val;
arr[2 + i * 4 + v][v] = q - val++;
arr[3 + i * 4 + v][n - 1 +
v] = val;
arr[3 + i * 4 + v][v] = q - val++;
arr[4 + i * 4 + v][v] = val;
arr[4 + i * 4 + v][n - 1 +
v] = q - val++;
}
arr[n - 3 +
v][v] = val;
arr[n - 3 +
v][n - 1 +
v] = q - val++;
arr[n - 2 +
v][n - 1 +
v] = val;
arr[n - 2 +
v][v] = q - val++;
}
//构造偶数阶同心幻方
void evenorder(
int n)
{
int k =
n / 2 - 2;
//层数
for (
int h = 0; h < k; h++)
{
int nn =
n - h * 2;
if (nn % 4 == 0)even2(nn, h, 2 * h * (
n - h) + 1,
n *
n + 1);
else even1(nn, h, 2 * h * (
n - h) + 1,
n *
n + 1);
}
hai_er(4, k, (n *
n - 16) / 2);
//对角线法填写4阶幻方
}
N=20时的输出:
参考:
1. 最简奇阶幻方镶边法(再简化) - 知乎 (zhihu.com)
2. 构造镶边幻方的代码法 - 百度文库