-2

我必须创建生成随机 NxN 幻方的函数,其中所有列和行的总和等于 S。变量 N 和 S 必须是用户输入。我已经创建了在满足给定条件时绘制正方形并打破循环的函数。它适用于像 3x3 或 4x4 这样的小方块,但对于较大的方块来说效率极低。矩阵内的所有数字都必须是整数,对角线不需要相等的行和。任何建议如何解决这个问题?

4

1 回答 1

2

由于任何幻方也是半幻方(不必有对角线来总结幻方常数),要回答这个问题就足以提供一种有效的算法来生成真正的幻方。解决幻方的经典算法之一如下(Robin KS Hankin引用):

在 4m 左右的正方形中,遮蔽长主对角线。然后将所有主要对角线与长对角线相距 4 个单元格的倍数遮蔽。对小对角线做同样的事情。然后,从左上角的“1”开始,从左到右,从上到下,从 1 数到 n^2,用适当的数字填充阴影方块,省略无阴影的方块。以相同的方式填充剩余的(无阴影的)正方形,从右下角开始,向左和向上移动。

您可能会发现 R package magic是研究高效魔方生成算法的有用资源。从包源中可以清楚地看出,问题可以分为三种不同的情况:

"magic" <-
function (n) 
{
    if(length(n)>1){
      return(sapply(n,match.fun(sys.call()[[1]])))
    }
    n <- round(n)
    if (n == 2) {
        stop("Normal magic squares of order 2 do not exist")
    }
    if (n%%2 == 1) {
        return(as.standard(magic.2np1(floor(n/2))))
    }
    if (n%%4 == 0) {
        return(as.standard(magic.4n(round(n/4))))
    }
    if (n%%4 == 2) {
        return(as.standard(magic.4np2(round((n - 2)/4))))
    }
    stop("This cannot happen")
}

即使是大的,执行时间magic也非常小n

> system.time(result <- magic(2017))
   user  system elapsed 
  1.256   0.316   1.573

最后,如果您真的只想要一个半幻方而不是真正的幻方,您可以随时交换结果方阵的任意两列。此操作不会影响行和列的总和,但肯定会破坏对角线的总和。

于 2017-06-04T08:45:19.607 回答