转载地址:http://blog.csdn.net/fengchaokobe/article/details/7437767
所谓n阶幻方问题,俗称“横竖斜相加和相等”(我们当时就是这么叫的)。用术语说就是:在一个N行N列的方格表中,有1,2,3......N*N-1,N*N这N*N个整数,且其对角线、横行、纵行的数字和都相等。
好了,在具体详解该问题之前,我们先看个例子,熟悉一下,如下图所示:
1.奇数阶幻方
我记得基数阶幻方有个口诀,有了这个口诀,走遍奇数幻方都不怕。其实这个口诀也是实现奇数幻方的步骤。
先填上行正中央,
依次斜填切莫忘。
上格没有顶格填,
顶格没有底格放。
附注:如果上述口诀有什么问题,请留言说明,谢谢!
ok,奇数幻方就讲完了,就这么简单。权当找乐子!
2.偶数阶幻方
说实话,偶数阶幻方我一直以为只有一种,就是2*n阶幻方问题。查了一下才知道偶数阶幻方也分为两小类。
①.4*n阶幻方
4*n阶幻方的生成其实很简单,即对方格中对角线上的数据,先以一条对角线(称对角线一)为对称轴,交换另一对角线(称对角线二)的数据;然后以对角线二 为对称轴,交换对角线一的数据。说的直白一点,假设矩阵名为MagicSquare,就是交换MagicSquare[i,j]和 MagicSquare[n-1-i,n-1-j]。老办法,作图来说明。图如下:
②.4*n+2阶幻方
4*n+2,乍一看就较4*n麻烦了,事实也是如此,不过它的思想也简单。就是将4*n+2看做2*(2*n+1),这样一来就转化成了四个2*n+1求幻方。
附注:下面的我以6阶幻方为例,那么,4*n+2=6,所以n=1。
我通过描述每个步骤加上图形的方式来表述4*n+2阶幻方实现的过程。
第一步:把整个表格分成4个(2*n+1)*(2*n+1)的小表格,分别叫A,B,C,D。见下图
第二步:这样A,B,C,D个小表格就成奇数幻方问题了。
①.将1,2,...,(2*n+1)*(2*n+1)这些数划分给A,并对A实现奇数幻方;
②.将(2*n+1)*(2*n+1)+1,...,2*(2*n+1)*(2*n+1)这些数划分给B,并对B实现奇数幻方;
③.将2*(2*n+1)*(2*n+1)+1,...3*(2*n+1)*(2*n+1)这些数划分C,并对C实现奇数幻方;
④.将3*(2*n+1)*(2*n+1)+1,...4*(2*n+1)*(2*n+1)这些数划分D,并对D实现奇数幻方。
见下图
第三步:从A表中的中心(即第n行的MagicSquare[n][n])开始,按照从左向右的方向,标出n个数,A表中的其他行则标出最左边的n格中的数(在图中用红色背景标出)。并且将这些标出的数和C表中的对应位置互换。见下图
第四步:在B表中的中心(如上解释)开始,自右向左,标出n-1列,将B中标出的数据与D表中对应位置的数据交换。但是6阶幻方中,n-1此时等于0,所以B与D不用做交换。
至此,这个幻方就成了,如下图。
附注:以上几个问题的程序就不送上了,有兴趣的朋友可以自己写一下。
1 奇数阶幻方构造法
(1) 将1放在第一行中间一列;
(2) 从2开始直到n×n止各数依次按下列规则存放:按 45°方向行走,向右上,即每一个数存放的行比前一个数的行数减1,列数加1
(3) 如果行列范围超出矩阵范围,则回绕。例如1在第1行,则2应放在最下一行,列数同样加1;
(4) 如果按上面规则确定的位置上已有数,或上一个数是第1行第n列时,则把下一个数放在上一个数的下面。
2 偶数阶幻方构造
2.1 4m阶的幻方
(1) 把数1到n×n按从上至下,从左到右顺序填入矩阵
(2) 将方阵的所有4×4子方阵中的两对角线上位置的数关于方阵中心作对称交换,即a(i,j)与a(n-1-i,n-1-j)交换,所有其它位置上的数不变。
------------->
3 4m+2阶幻方
(1) 首先构造n-2=4m的幻方,然后放在n阶幻方的中心
(2) 将4m阶幻方中每个数都加上8m+2;
(3) 将1,2,...,8m+2 与 ....(4m+2)2成对排在外围的一圈,如下图,注意中心的4m阶未加上8m+2,且保证每对数相加=1+(4m+2)2
由n阶幻方想到的
幻方问题就说完了,比较一下我还是感觉奇数阶幻方有意思,而且比偶数阶幻方问题容易些,没有那么麻烦。按说写到此本应该结束了,可是我突发奇想,n阶幻方 这个问题利用数学知识很容就能解决,那么我想问一下大家:在平时写程序思考算法的时候,你是否会利用数学知识来解决问题呢?
假如这个问题让你在限定的时间内编程来实现.如果你对n阶幻方很了解,知道奇偶两种情况的做法,好,那没有问题,恭喜你!但是,恰巧你对n阶幻方不是很了 解,也不知道奇偶阶幻方的做法,那这个问题你会怎么解决?用枚举还是用其他什么算法。这是你不得不考虑的。
说到这,我又想到了一个例子,如:求1,2,...,99,100的和,请编程实现。你会怎么做?这个确实很简单,我相信多数朋友都会用一个for或是一 个while来解决问题。那还有没有更简单的办法呢?当然有,利用数学知识来解决,1,2,...,99,100就是一个等差数列,等差数列求和的公式 S=(首项+末项)*项数/2,直接得出结果。哪个效率更高,不言而喻。所以说,数学知识在我们编程中很有用,只是我们经常考虑不到而已!