矩阵中的幻方

来源

关于幻方

​ 幻方是一种将数字安排在正方形格子中,使每行、列和对角线上的数字的和都相等的方法。幻方可以分为完全幻方、乘幻方和高次幻方等。
​ 完全幻方指一个幻方行、列、主对角线机泛对角线各数之和均相等。
​ 乘幻方指一个幻方行列、对角线各数乘积相等。

​ 高次幻方是指,当组成幻方各数替换为2,3,……,n次幂时,仍能满足条件者,称此幻方为n次幻方。n阶幻方是由前n2(n的2次方)个自然数组成一个n阶方阵,其各行、各列及两条对角线所含的n个数的和相等。计算任意阶幻方的各行、各列、各条对角线上所有数的和的公式是:S=n*(n2+1)/2。其中,n为幻方的阶数,所求的数为S。

幻方

对平面幻方的构造,分为三种情况:n为奇数,n为4的倍数,n为其他偶数(4*n+2的形式)

奇数阶幻方

​ n为奇数时,最简单: (1)将1放在第一行中间一列;

​ (2)从2开始直到n*n止各数依次按下列规则存放:

​ 按45°方向行走,如右上

​ 每一个数存放在的行比前一个的行数减一,列数加一

​ (3)如果行列范围超出矩阵范围,则回绕。

​ 例如:1在第一行,2则放在最下一行,列数加一

​ (4)如果按上面的规则确定的位置上已有数字,或上一个数是第1行第n列时,则把

​ 下一个数放在上一个数的下面。

偶数阶幻方

普通偶数阶幻方

​ 当n为非4的倍数的偶数(即4n+2)时:首先把大方阵分解为4个奇数(2m+1)子方阵。

​ 按上述奇数阶幻方给4个子方阵对应赋值:

​ 由小到大依次为上左子阵(i),下右子阵(i+v),上右子阵(i+2v),下左子阵(i+3v)

​ 即4个子阵对应元素相处v,其中v=n*n/4。

​ 四个子矩阵由小到大排列方式为①③④②

​ 然后作相应的元素交换:a(i,j)与a(i+u,j)在同一列在对应交换(j<t或j>n-t+2),a(t-1,0)与a(t+u,0);a(t-1,t-1)与a(t+u-1,t-1)两对元素交换,其中u=n/2,t=(n+2)/4。

​ 上述交换是行列及对角线上的元素之和相等。

4的倍数阶幻方

​ 采用对称元素交换法。

​ 首先把数1到n*n按从上到下,从左到右顺序填入矩阵;

​ 然后将方阵的所有4*4子方阵中的两对角线上位置的数关于方阵中心作对称交换,即a(i,j)与a(n+1-i,n+1-j)交换,所有其他位置的数不变。

​ 以上方法值适合于n为4或4的倍数时。

840. 矩阵中的幻方

3 x 3 的幻方是一个填充有从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。

给定一个由整数组成的 grid,其中有多少个 3 × 3 的 “幻方” 子矩阵?(每个子矩阵都是连续的)。

输入: [[4,3,8],
      [9,5,1],
      [2,7,6]]
输出: 1
解释: 
下面的子矩阵是一个 3 x 3 的幻方:
438
951
276

而这一个不是:
384
519
762

总的来说,在本示例所给定的矩阵中只有一个 3 x 3 的幻方子矩阵。

算法实现

  • 3x3阶幻方
class Solution(object):
    def numMagicSquaresInside(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        R, C = len(grid), len(grid[0])
        
        def magic(a, b, c, d, e, f, g, h, i):
            return (sorted([a, b, c, d, e, f, g, h, i]) == list(range(1, 10)) and 
            (a + b + c == d + e + f == g + h + i == a + d + g == b + e + h == c + f +i == a + e + i == c + e + g == 15))
        ans = 0
        for r in range(R-2):
            for c in range(C-2):
                if grid[r + 1][c + 1] == 5:
                    if magic(grid[r][c], grid[r][c+1],grid[r][c+2],
                    grid[r+1][c],grid[r+1][c+1],grid[r+1][c+2],
                    grid[r+2][c],grid[r+2][c+1],grid[r+2][c+2]):
                        ans += 1
        return ans
  • 5x5阶算法
def numMagicSquaresInside(self, grid):
    R, C = len(grid), len(grid[0])

    def magic(a, b, c, d, e, f, g, h, i,j,
              k,l,m,n,o,p,q,r,s,t,
              u,v,w,x,y):
        return (sorted([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y]) == list(range(1, 26)) and (
                    a + b + c + d + e == f + g + h + i + j == k + l + m + n + o == p + q + r + s + t == u + v + w + x + y ==
                    a + f + k + p + u == b + g + l + q + v == c + h + m + r + w == d + i + n + s + x == e + j + o + t + y ==
                    a + g + m + s + y == e + i + m + q + u == 65))

    ans = 0
    for r in range(R - 4):
        for c in range(C - 4):
            if grid[r + 2][c + 2] == 13:
                if magic(grid[r][c], grid[r][c + 1], grid[r][c + 2], grid[r][c + 3], grid[r][c + 4],
                         grid[r + 1][c], grid[r + 1][c + 1], grid[r + 1][c + 2], grid[r + 1][c + 3], grid[r + 1][c + 4],
                         grid[r + 2][c], grid[r + 2][c + 1], grid[r + 2][c + 2], grid[r + 2][c + 3], grid[r + 2][c + 4],
                         grid[r + 3][c], grid[r + 3][c + 1], grid[r + 3][c + 2], grid[r + 3][c + 3], grid[r + 3][c + 4],
                         grid[r + 4][c], grid[r + 4][c + 1], grid[r + 4][c + 2], grid[r + 4][c + 3], grid[r + 4][c + 4]):
                    ans += 1
    return ans

5x5阶幻方填法

来源

一、Merzirac法生成奇阶幻方

在第一行居中的方格内放1,依次向右上方填入2、3、4…,如果右上方已有数字,则向下移一格继续填写。如下图用Merziral法生成的5阶幻方:
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
Merzirac法,有人也叫楼梯法,我管它叫斜步法,即走X+Y斜步(数字按右上方顺序填入),-Y跳步(如果右上方已有数字或出了对角线,则向下移一格继续填写)。
其实斜步法可以向4个方向依次填写数字,即右上、右下、左上、左下4个方向,每种斜步都可有2种跳步,即左(右)跳步、上(下)跳步。
对于X+Y斜步相应的跳步可以为-X,-Y。 【记住,跳步是X+Y斜步的X(或Y)相反方向即可。如右上方向斜步,跳步就为向左(或向下)一步;左下方向斜步,跳步就为向右(或向上)一步;等等等等】

二、loubere法生成奇阶幻方

在居中的方格向上一格内放1,依次向右上方填入2、3、4…,如果右上方已有数字,则向上移两格继续填写。如下图用Louberel法生成的5阶幻方:
23 6 19 2 15
10 18 1 14 22
17 5 13 21 9
4 12 25 8 16
11 24 7 20 3
上述loubere法可以记作X+Y斜步(数字按右上方顺序填入),2Y跳步(如果右上方已有数字或出了对角线,则向上移二格继续填写)。对于X+Y斜步相应的跳步可以为2X,2Y。 【记住,跳步是X+Y斜步的X(或Y)相同方向即可。】
2Y跳步,则在居中的方格向上一格放1里,按上斜步,2Y跳步的方法构成幻方。
-2Y跳步,则在居中的方格向下一格放1里,按下斜步,-2Y跳步的方法构成幻方。
2X跳步,则在居中的方格向右一格放1里,按右斜步,2X跳步的方法构成幻方。
-2X跳步,则在居中的方格向左一格放1里,按左斜步,-2X跳步的方法构成幻方。

三、horse法生成奇阶幻方

对于所有的奇阶幻方,在第一行居中的方格内放1,向左走1步,下走2步以跳马步,依次填入2、3、4…,若出到方阵下方,把该数字填到本该填数所在列上方相应的格;若出到方阵右方,把该数字填到本该填数所在行的左方相应的格;如果落步格已有数字, 则向下移一格继续填写。如下图用Horse法生成的5阶幻方:
23 12 1 20 9
4 18 7 21 15
10 24 13 2 16
11 5 19 8 22
17 6 25 14 3
n阶奇阶幻方,若n为不是3的倍数,那么在任意一格内放1,向左走1步,下走2步以跳马步,依次填入2、3、4…,若出到方阵下方,把该数字填到本该填数所在列上方相应的格;若出到方阵右方,把该数字填到本该填数所在行的左方相应的格;如果落步格已有数字, 则向上移一格继续填写。如下图用Horse法生成的5阶幻方:
1 14 22 10 18
25 8 16 4 12
19 2 15 23 6
13 21 9 17 5
7 20 3 11 24

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值