由n*n个数字所组成的n阶方阵,若具有各对角线、各横列与纵行的数字和都相等的性质,则称为魔方阵。这个相等的和称为魔术数字。若填入的数字是从1到n*n,称此种魔方阵为n阶正规魔方阵。
如下所示为一个3阶魔方阵和一个四阶魔方阵。
魔方阵的构建方法很多,一般将n分为三类,这三类n构成的魔方阵的算法各不相同。
(1)当n为奇数,即n=2*k+1时,常采用简捷连续填数法。
(2)当n为单偶数(n是偶数,但又不能被4整除),即n=4*k+2时,常采用井字调整法。
(3)当n为双偶数(n能被4整除),即n=4*k时,常采用双向翻转法。
- 构造奇数阶魔方阵
奇数阶魔方阵的构造方法为:
首先把1放到顶行的正中间,然后把后继数按顺序放置在右上斜的对角线上,并作如下修改:
(1)当到达顶行时,下一个数放到底行,好像它在顶行的上面;
(2)当到达最右端列时,下一个数放在最左端列,好像它紧靠在右端列的右方;
(3)当到达的位置已经填好数时,或到达右上角的位置时,下一个数就放在刚填写数的位置的正下方。
下面以构造一个3阶魔方阵为例,说明这种方法的构造过程,具体如图1所示。
图1 简捷连续填数法构造3阶魔方阵
- 编程思路
程序中定义一个二维数组a[N][N]来保存方阵,初始时,数组中所有元素均置0。
用变量row和col来存储待填数字num在方阵中的位置,由于第1个数字放在顶行的正中间,因此初始时,行row=0,列col=n/2,待填写数字num=1。
采用简捷连续填数法构造方阵的过程是一个循环程序,描述为:
While (待填写数字num<=n*n)
{
确定待填写数字num应该填写的位置row和col;
填写num,即a[row][col]=num;
Num++; // 下一个待填写的数字
}
程序中,确定待填写位置的方法是:
(1)后继数按顺序放置在右上斜的对角线上,即row--; col++;
(2)有三种情形需要调整。
当到达顶行时(即row<0), row=n-1;
当到达最右端列时(即col==n), col=0;
当到达的位置已经填好数时(即(a[row][col]!=0), row+=2; col--;
(3)有一种情况,当到达右上角的位置时(row==0 && col==n-1),直接进行特殊处理,row++ 。
- 源程序及运行结果
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int a[9][9],row,col,num,n;
cin>>n;
for (row=0;row<n;row++) // 初始化,数组中所有元素均置0
for (col=0;col<n;col++)
a[row][col]=0;
row=0; col=n/2; num=1;
a[row][col]=num;
while (num<n*n)
{
num++;
if (row==0 && col==n-1) // 到达右上角的位置
row++;
else
{
row--; col++;
if (row<0) row=n-1;
if (col==n) col=0;
if (a[ro