魔方阵(各幻方)

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;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王也枉不了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值