龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > C/C++开发 >

关于魔方阵的解法

时间:2009-12-22 15:42来源:未知 作者:admin 点击:
分享到:
首先把从1~n2的整数按从小到大的顺序排列成一个n×n的方阵A进行观察。(本文中所有n都是指大于1的奇数,下文中均以“A”代表这类顺序排列的n×n方阵) 以5阶阵为例:以下是A方阵

首先把从1~n2的整数按从小到大的顺序排列成一个n×n的方阵A进行观察。(本文中所有n都是指大于1的奇数,下文中均以“A”代表这类顺序排列的n×n方阵)

  以5阶阵为例:以下是A方阵

  1 2 3 4 5

  6 7 8 9 10

  11 12 13 14 15

  16 17 18 19 20

  21 22 23 24 25

  下边是魔方阵B:

  12 16 25 4 8

  6 15 19 23 2

  5 9 13 17 21

  24 3 7 11 20

  18 22 1 10 14

  先假设n阶奇次魔方阵B是存在的,从A中可以看出,B的任一元素在A中都有唯一确定的行号和列号组合(y,x)。

  分离出B中所有元素在A中的行号y来构成n×n方阵I,让I(i,j)等于从B(i,j)分离出来的y;(如I(1,1) =3,即12在A中的行号A(3,2);I(1,2)=4,即16在A中的行号A(4,1)。)以下是I方阵:

  3 4 5 1 2

  2 3 4 5 1

  1 2 3 4 5

  5 1 2 3 4

  4 5 1 2 3

  同样分离出B中所有元素在A中的列号y来构成n×n方阵J,让J(i,j)等于从B(i,j)分离出来的x。以下是J方阵

  2 1 5 4 3

  1 5 4 3 2

  5 4 3 2 1

  4 3 2 1 5

  3 2 1 5 4

  观察方阵I特征为:

1.组成方阵的数为1~n的整数;

2.任一行、列均遍历1~n的所有整数;

3.主对角线上的数均为(n+1)/2,辅对角线遍历1~n的所有整数。

方阵J特征前两点同I,区别是第三点,辅对角线上的数均为(n+1)/2,主对角线遍历1~n的所有整数。 另外还有轻易忽略的一点,I、J方阵对应位置上的数字组合[I(i,j),J(i,j)]是唯一的。

    综合以上的结论可以知道:B(i,j)=(I(i,j)-1)×n+J(i,j)。所以只要构造出这样两个只含1~n的数的方阵I和J,就可以确定一个n×n的魔方阵。

  现在,问题就转化为怎样构造分别满足I和J的特征的两个n×n方阵。其实完成这样的算法是很简单的,可以按以下方法实现:

1) 方阵I的第一行由(n+1)/2打头,后面依次为前一个数关于n的循环后继;

2)方阵I的第i+1行由第i行循环右移得到。

本人给出的程序:

main()

  {

  int n,i,j;

  int a[20][20],x[20][20],y[20][20];/* a数组为最后结果数组文中的B方阵,X,Y分别是文中提到的数组I,J*/

  printf("please input the number:");

  scanf("%d",&n); /*输入需要的数组维数*/

   x[0][0]=(n+1)/2;

   for(j=1;j

   {

   if(x[0][j-1]==n) x[0][j]=x[0][j-1]+1-n;

   else x[0][j]=x[0][j-1]+1;

   }/*给x中的第一行元素赋值*/

for(i=1;i

   for(j=0;j

   {

   if(j-1<0) x[i][j]=x[i-1][j-1+n];

   else x[i][j]=x[i-1][j-1];

  } /*通过变换给X的所有元素赋值*/

  clrscr();

  printf("X:

");

  for(i=0;i

   for(j=0;j

   {

   printf("%3d",x[i][j]);

   if(j==n-1)printf("

");

   }/*输出X数组*/

  for(i=0;i

   for(j=0;j

   y[i][j]=x[i][n-1-j];/*通过文中提到的公式给Y数组赋值*/

  printf("Y:

");

  for(i=0;i

   for(j=0;j

   {printf("%3d",y[i][j]);

   if(j==n-1)printf("

");

   }/*输出Y数组*/

  for(i=0;i

   for(j=0;j

   a[i][j]=(x[i][j]-1)*n+y[i][j];

  printf("A:

");

  for(i=0;i

   for(j=0;j

   {printf("%5d",a[i][j]);

   if(j==n-1)printf("

");}

  /*输出A数组结果*/

  

}

  

收藏文章
表情删除后不可恢复,是否删除
取消
确定
图片正在上传,请稍后...
评论内容为空!
还没有评论,快来抢沙发吧!

热评话题

按钮 内容不能为空!
立刻说两句吧! 查看0条评论
精彩图集

赞助商链接