定义:
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 }