定义:
n阶矩阵(n×n),满足每一行、每一列、对角线元素的和相同,n>=3
分类:
1、奇数阶魔方阵
2、双偶数阶魔方阵(4*k)
3、单偶数阶魔方阵(4*k+2)
1、奇数阶魔方阵
1)首行的中间赋值1,arr[0][n/2]=1
2)将2到n2依次赋值:整体规律是 行数减一,列数加一
3)特殊情况:行标i=0时,减一后赋值最后一行i=n-1;列标j=n-1时,加一赋值第一列j=0
4)特殊情况:原位置已被占用,则下一个数放在上一个数的下面


1 void GetOddMagic(int arr[][MAX], int n)
2 {
3 int row = 0, col = n / 2, prow, pcol;
4 arr[row][col] = 1;
5 int t = 2;
6 while (t <= n*n)
7 {
8 prow = row, pcol = col;//记录row,col的副本
9 row = row>0 ? (--row) : (n - 1);//行数减一
10 col = col<(n - 1) ? (++col) : 0;//列数加一
11 if (arr[row][col])
12 {
13 row = prow, col = pcol;
14 arr[++row][col] = t;
15 }
16 else
17 arr[row][col] = t;
18 t++;
19 }
20 }
2、双偶数阶魔方阵(4*k)
1)初始化为0矩阵,将矩阵看成4块
2)左上和右下1/4块:奇行偶列,偶行奇列的位置上赋值1;右上和左下1/4块:奇行奇列,偶行偶列的位置上赋值1
3)从左到右、上到下,遇到1则赋值,遇0不赋值。n*n->1
4)从左到右、上到下,遇到0则赋值,遇非零不赋值。1->n*n

对于2):先实现左上部分块,然后反射给另外三面,左上->右上,上半->下半(小方阵的映像)


1 void getDbEvenMatrix(int arr[][MAX],int n)
2 {
3 int i, j, k;
4 for (i = 0; i < MAX; i++)
5 for (j = 0; j < MAX; j++)
6 arr[i][j] = 0;
7 for (i = 0; i<n; i++)
8 for (j = 0; j<n; j++)
9 {
10 if (i<n / 2 && j<n / 2 || i >= n / 2 && j >= n / 2)
11 if (i % 2 == 0 && j % 2 == 1 || i % 2 == 1 && j % 2 == 0)
12 arr[i][j] = 1;
13 if (i >= n / 2 && j<n / 2 || i<n / 2 && j >= n / 2)
14 if (i % 2 == 0 && j % 2 == 0 || i % 2 == 1 && j % 2 == 1)
15 arr[i][j] = 1;
16 }
17 k = n*n;
18 for (i = 0; i<n; i++)
19 for (j = 0; j<n; j++)
20 {
21 if (arr[i][j])
22 arr[i][j] = k;
23 k--;
24 }
25 k = 1;
26 for (i = 0; i<n; i++)
27 for (j = 0; j<n; j++)
28 {
29 if (!arr[i][j])
30 arr[i][j] = k;
31 k++;
32 }
33 //输出双偶数魔方阵
34 for (i = 0; i<n; i++)
35 {
36 for (j = 0; j<n; j++)
37 cout << arr[i][j] << '\t';
38 cout << endl;
39 }
40 }
3、单偶数魔方阵
1)分四块A,B,C,D,得到奇数魔方阵A,看做n/2阶方阵
2)A每个元素加(n/2)*(n/2)得到B;B每个元素加(n/2)*(n/2)得到C;C每个元素加(n/2)*(n/2)得到D
3)交换A和D中部分值:遍历A的行,遇到中间行,交换从中间列向右m列;非中间行,交换从第一列向右m列
4)交换C和D中部分值:遍历C的行,所有行,交换从中间列向左m-1列


1 void getSgEvenMatrix(int arr[][MAX],int n)
2 {
3 int i, j, k;
4 k = (n / 2)*(n / 2);
5 for (i = 0; i < MAX; i++)
6 for (j = 0; j < MAX; j++)
7 arr[i][j] = 0;
8 getOddMagic(arr, n/2);
9 //得到B,C,D
10 for(i=0; i<n/2; i++)
11 for (j = 0; j < n / 2; j++)
12 {
13 arr[i + n / 2][j + n / 2] = arr[i][j] + k;
14 arr[i][j + n / 2] = arr[i][j] + 2 * k;
15 arr[i + n / 2][j] = arr[i][j] + 3 * k;
16 }
17 //A<->D,交换m列,按行分类
18 for(i=0; i<n/2; i++)
19 {
20 if(i == n/2/2)
21 {
22 for(j=i; j<n/2-1; j++)
23 {
24 k = arr[i][j];//k已经无用
25 arr[i][j] = arr[i+n/2][j];
26 arr[i+n/2][j] = k;
27 }
28 }
29 else
30 {
31 for(j=0; j<n/2/2; j++)
32 {
33 k = arr[i][j];
34 arr[i][j] = arr[i+n/2][j];
35 arr[i+n/2][j] = k;
36 }
37 }
38 }
39 //C<->B,交换中间列向左m-1列
40 for(i=0; i<n/2; i++)
41 for(j=0; j<(n/2-1)/2-1; j++)
42 {
43 k = arr[i][n/2+n/2/2-j];
44 arr[i][n/2+n/2/2-j] = arr[i+n/2][n/2+n/2/2-j];
45 arr[i+n/2][n/2+n/2/2-j] = k;
46 }
47 for (i = 0; i<n; i++)
48 {
49 for (j = 0; j<n; j++)
50 cout << arr[i][j] << '\t';
51 cout << endl;
52 }
53 }
