MagicSquare Odd(奇数幻方) 详解2

这次我们来谈一谈为什么罗伯法只能用于奇数阶的幻方。

首先还是放代码

 public static boolean generateMagicSquare(int n) throws IOException {
        if(n<0||n%2==0){
            System.out.println("输入数据不合法,必须是正奇数才可以。");
            return false;
        }
        int magic[][] = new int[n][n];                      //创建magic二维数组,用于储存magic矩阵
        int row = 0, col = n / 2, i, j, square = n * n;     //根据输入的n来设定常量
        for (i = 1; i <= square; i++) {                     //逐次生成magic矩阵里的所有数值
            magic[row][col] = i;                            //从第0行的中间位置开始生成,从1开始,后一个生成的值比前一个大1
            if (i % n == 0) {                             //生成好相当于一行数目的值之后就在下一行开始赋值,以免重复赋值
                row++;
            }
            else {
                if (row == 0) row = n - 1;                  //如果row对应第一行,就跳转为最后一行
                else    row--;                              //而如果不是,就将row-1,上移一行
                if (col == (n - 1))                         //对于col同理,只不过增减方向相反
                col = 0;
                else    col++;
            } }
        try(FileWriter filewriter = new FileWriter("src\\P1\\txt\\6.txt")){
            for (i = 0; i < n; i++) {
                for (j = 0; j < n; j++)
                    filewriter.write(magic[i][j] + "\t");
                filewriter.write("\n");
            }
        }

        return true;
    }

在上次的论述中,我们知道了幻方构建的大致流程。在这个程序里就是不停地向右上方移动读/写头,然后每到n的倍数时,切换一下写的行。想起了这些,就可以很轻松地意识到,当i为n的倍数,并且row值为n-1时,经过行数+1的代码段,row的值会直接变成n,出现数组越界,从而导致程序异常退出。

如果还不明白的话,就可以看看我下面的推演:以n=4的情况为例

 首先,在n=4的情况中,row值为0,col值为n/2=4/2=2.因此写1的位置是row[0][2],和n=5的情况一致。

随后,我们按照之前的规律,从1一直写到8,就会发现当写完8之后,i值为4的倍数,并且row值为n-1,经过程序row值会变为n,直接越界。因此程序会异常退出。

那么很显然,将这条语句改为row=(row++)%n即可让偶数情况下不报错。

那么,是不是这样就可以让这个程序生成偶数阶的MagicSquare了呢?大家可以自己跑程序试一试,我这里就直接给出结果:不能

这是按照之前代码规律,生成的4阶幻方。第一行之和= 9 + 15 + 1 + 7 = 32,而第二行之和 = 14  +  4  +  6 + 12 = 36,显然不相等。由此我们能非形式化得出,这个程序只能适用奇数阶的幻方。

那有没有能够更加形式化的证明方法呢?

我们从每次i % n == 0 的情况入手,每次i % n == 0后,row的相对位置相比之前都会下降2位,设下降了j次,其中j为自然数。

我们需要对方程2*j =k*n进行求解,看是否有小于等于n的自然数解。

其中k是任意正整数。

在n为奇数的情况下,j*2仅在j=n的情况下整除n(n/2不是整数,取不到),只有当i==n时,row才会等于n;而在n为偶数情况下,j能取到n/2,使得程序中出现i<n但row=n的情况。

掌握了这点,这个程序就可以控制输入n的奇偶性:如果是奇数,就正常运行程序,如果是偶数的话及就会数组下标越界,直接报错。

那么,回到刚才的话题,为什么在偶数情况下生成的不是magic square呢?

这是因为,在这种数字循环出现重复的情况下,就会出现余数小的和小的加在一起,余数大的和大的加在一起的情况,结果就不是magic square了。

还是以这个图为例,我们已知第一横行的四个数之和为32,第二个横行的四个数之和为36,二者不等。 第一横行的四个数q值(不知道q值是什么的可以见详解1)分别是1,3,1,3,第二横行的四个q值分别是2,4,2,4,因此两个横行之和并不相等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值