1.什么叫幻方
幻方,好比一个n行n列的正方形,共有n……n2个格子,将1、2、3、……、n2这些数字放到这些格子里,使其每行的和、每列的和及两条对角线的和都是一个相同的数SUM,SUM被称为幻和。
且:
1.当n为奇数时,称为奇数阶幻方。
2.当n为偶数时,称为偶阶幻方。
3.当n可被4整除时,称方为双偶幻方。
4.当n不可被4整除时,称为单偶幻方。
2.奇幻方解法
奇魔方(阶数n = 2 * m + 1,m =1,2,3……)规律如下:
数字1位于方阵中的第一行中间一列;
数字a(1 < a ≤ n2)所在行数比a-1行数少1,若a-1的行数为1,则a的行数为n;
数字a(1 < a ≤ n2)所在列数比a-1列数大1,若a-1的列数为n,则a的列数为1;
如果a-1是n的倍数,则a(1 < a ≤ n2)的行数比a-1行数大1,列数与a-1相同。
3.双偶魔方解法
阶数n = 4 * m(m =1,2,3……)的魔方(双偶魔方)
即:
按数字从小到大,即1,2,3……n^2顺序对魔方阵从左到右,从上到下进行填充;
将魔方中间n/2列的元素上、下进行翻转;
将魔方中间n/2行的元素左、右进行翻转。
4.单偶魔方解法
考虑到单偶魔方的特性我们可以将其分成奇魔方求解:
阶数n = 4 * m + 2(m =1,2,3……)的魔方(单偶魔方)
设k = 2 * m + 1;
将魔方分成A、B、C、D四个k阶方阵,如下图单偶魔方分解这四个方阵都为奇方阵,利用上面讲到的方法依次将A、D、B、C填充为奇魔方。
交换A、C魔方元素,对魔方的中间行,交换从中间列向右的m列各对应元素;对其他行,交换从左向右m列各对应元素。
交换B、D魔方元素,交换从中间列向左m – 1列各对应元素。
5.完整代码
值得一提的是,本代码为改变平常的向右上为左上
#include <iostream>
using namespace std;
int matrix[200][200] = {0};
//生成奇数幻方
void COMS(int n)
{
int x=0,y,mun =1;
y=n/2;
while ( mun <= n*n )
{
matrix[x][y] = mun;
//通过x0、y0检测右上的是否已经填入数字
int x0=x;
int y0=y;
x0--;
y0--;
//超界处理
if(x0<0)
x0+=n;
if(y0 < 0)
y0= n-1;
if(0 == matrix[x0][y0] )
{
x = x0;
y = y0;
}
else
{
//若有数字填入之前数字的下方
x++;
if(x == n)
x = x-n;
}
mun ++;
}
}
//生成双偶幻方
void CDEMS( int n )
{
int num = 1;
//从1到n的平方依次赋值
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
matrix[i][j] = num++ ;
//小正方形的对角线上的数字取其补数
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(i%4==0 && abs(i-j)%4 == 0)
for(int k=0;k<4;k++)
matrix[i+k][j+k] = abs( n*n +1 - matrix[i+k][j+k] );
else if (i%4==3 && (i+j)%4 == 3)
for(int k=0;k<4;k++)
matrix[i-k][j+k] = abs( n*n +1 - matrix[i-k][j+k] );
}
}
//生成单偶幻方
void CSEMS(int n)
{
int k = n/2;
COMS(k);
//赋初值,左上最小,右下其次,右上再次,左下最大
for(int i=0;i<k;i++)
for(int j=0;j<k;j++)
{
matrix[i+k][j+k] = matrix[i][j] + k*k;
matrix[i][j+k] = matrix[i][j] + k*k*2;
matrix[i+k][j] = matrix[i][j] + k*k*3;
}
//公式 n=4m+2
int m = (n-2) / 4;
//交换x方向正中行的从左至右m-1个
for(int i=0;i<m-1;i++)
{
int buf = matrix[k/2][i];
matrix[k/2][i] = matrix[k/2+k][i];
matrix[k/2+k][i] = buf;
}
int buf = matrix[k/2][k/2];
//以及正中间的数
matrix[k/2][k/2] = matrix[k/2+k][k/2];
matrix[k/2+k][k/2] = buf;
//交换除x正中间行的其他行对应数字m个
for(int i=0;i<k;i++)
for(int j=0;j<k/2;j++)
{
if(i != k/2)
{
int temp = matrix[i][j];
matrix[i][j] = matrix[i+k][j];
matrix[i+k][j] = temp;
}
}
//交换最右边m-1个数字
for(int i=0;i<k;i++)
for(int j=n-1;j>n-1-(m-1) ; j--)
{
int buf = matrix[i][j];
matrix[i][j] = matrix[i+k][j];
matrix[i+k][j] = buf;
}
}
int main()
{
int n;
cin>>n;
if(n%2!=0)
COMS(n);
else if (n%4 == 0)
CDEMS(n);
else if (n%2 == 0)
CSEMS(n);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
cout<<matrix[i][j]<<" ";
cout<<endl;
}
return 1;
}