幻方,有时又称魔方(该称呼现一般指立方体的魔术方块)或纵横图,由一组排放在正方形中的整数组成,其每行、每列以及两条对角线上的数之和均相等。通常幻方由从到的连续整数组成,其中为正方形的行或列的数目。因此阶幻方有行列,并且所填充的数为从到。
幻方可以使用阶方阵来表示,方阵的每行、每列以及两条对角线的和都等于常数,如果填充数为,那么有
- 奇数阶幻方
- 4M阶幻方
- 4M+2阶幻方
- 把放置在第一行的中间。
- 顺序将等数放在右上方格中。
- 当右上方格出界的时候,则由另一边进入。
- 当右上方格中已经填有数,则把数填入正下方的方格中。
- 按照以上步骤直到填写完所有个方格。
根据幻方阶数的不同,产生幻方的方法也不区别
一般可以分为下了三种情况:
奇数阶幻方构造法
Siamese方法是构造奇数阶幻方的一种方法,说明如下:
(由于幻方的对称性,也可以把右上改为右下、左上以及左下等方位)
偶数阶幻方构造法
4M阶的情况
将4M阶分成M*M个4*4的块,每块里面值改变对角线和负对角线上的数字,将对角线上的数字 变成
4M+2阶的情况
这个情况的构造情况比较麻烦
详见http://blog.sina.com.cn/s/blog_639b95e90100i6h4.html
下面附上求n阶幻方的代码,n为以上三种情况
#include <stdio.h>
#include <string.h>
const int N = 101;
int n;
int magic[N][N];
void Swap(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
void PrintMagic(int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
printf("%d ", magic[i][j]);
printf("\n");
}
}
void CreateOddMagic(int n, int si = 0, int sj = 0, int add = 0)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
magic[si+i][sj+j] = 0;
i = 0;
j = n / 2;
magic[si+i][sj+j] = 1 + add;
int inc = 2;
while (inc <= n * n)
{
int ni = i - 1;int nj = j + 1;
if ((ni == -1 && nj == n) || (ni >= 0 && ni < n && nj >= 0 && nj < n && magic[si+ni][sj+nj]))
{
ni = i + 1;
nj = j;
}
else if (ni == -1)
{
ni = n - 1;
}
else if (nj >= n)
{
nj = 0;
}
magic[si+ni][sj+nj] = add + inc++;
i = ni;
j = nj;
}
//PrintMagic(n);
}
void Create4(int si, int sj, int n)
{
int i;
int j;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
if (i == j || i == 3 - j)
{
magic[si+i][sj+j] = n * n + 1 - magic[si+i][sj+j];
}
}
}
}
void Create4Magic(int n)
{
int i;
int j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
magic[i][j] = i * n + j + 1;
for (i = 0; i < n; i += 4)
{
for (j = 0; j < n; j += 4)
{
Create4(i, j, n);
}
}
}
void Create4M2Magic(int n)
{
int m = (n - 2) / 4;
int i;
int j;
memset(magic, 0, sizeof(magic));
int add = n * n / 4;
CreateOddMagic(n/2, 0, 0, 0);
CreateOddMagic(n/2, 0, n/2, 2* add);
CreateOddMagic(n/2, n/2, 0, 3 * add);
CreateOddMagic(n/2, n/2, n/2, add);
for (i = 0; i < n/2; i++)
{
for (j = 0; j < m - 1; j++)
{
Swap(magic[i][j], magic[i+n/2][j]);
}
if (i != m)
Swap(magic[i][j], magic[i+n/2][j]);
else
Swap(magic[i][m], magic[i+n/2][m]);
}
for (i = 0; i < n/2; i++)
{
for (j = n - m + 1; j < n; j++)
Swap(magic[i][j], magic[n/2+i][j]);
}
}
int main(void)
{
while (scanf("%d", &n) && n)
{
if (n % 2 == 1)
{
CreateOddMagic(n);
}
else if (n % 4 == 0)
{
Create4Magic(n);
}
else
{
Create4M2Magic(n);
}
PrintMagic(n);
}
return 0;
}