幻方的生成

来源:互联网 发布:著名网络暴力案例图片 编辑:程序博客网 时间:2024/04/28 02:44

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

幻方可以使用N阶方阵来表示,方阵的每行、每列以及两条对角线的和都等于常数M_2(N),如果填充数为1,2,\dots,N^2,那么有

M_2(N) = \frac{N(N^2+1)}{2}

根据幻方阶数的不同,产生幻方的方法也不区别

一般可以分为下了三种情况:

  1. 奇数阶幻方
  2. 4M阶幻方
  3. 4M+2阶幻方

奇数阶幻方构造法 

Siamese方法是构造奇数阶幻方的一种方法,说明如下:

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

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

\begin{bmatrix}8 & 1 & 6 \\3 & 5 & 7 \\4 & 9 & 2 \\\end{bmatrix}

偶数阶幻方构造法

4M阶的情况

将4M阶分成M*M个4*4的块,每块里面值改变对角线和负对角线上的数字,将对角线上的数字a_(ij) 变成(n^2+1)-a_(ij)

MagicSquareDoublyEven

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]);elseSwap(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;}




原创粉丝点击