多米诺骨牌棋盘的部分拼接是棋盘上放置多米诺骨牌,这样就不会有两个多米诺骨牌重叠。由多米诺骨牌拼成棋盘是一种局部拼贴,其中每个方块的棋盘都被一些多米诺骨牌覆盖。
我感兴趣的问题如下:多米诺骨牌$ N $棋盘的倾斜数是多少?
事实证明,对于$ M $棋盘b多米诺骨牌的$ M $的倾斜数实际上有一个明确的公式:
https://wikimedia.org/api/rest_v1/media/math/render/svg/1bc328b90d68fd765e2666ad0c62bb42b2e2bd10
我对这个问题的算法方法很感兴趣。我们只需要考虑$ N $均匀的情况($ N $奇数,倾斜数量显然是$ 0 $)。我想要解决的唯一算法是强力递归。
我创建了一个名为number_of_tilings(partial_tiling)的函数,它接受棋盘的局部平铺,并输出用多米诺骨牌覆盖未覆盖的正方形的方式的数量,这样我们最终得到一个平铺。
我创建了一个名为uncovered_square(partial_tiling)的辅助函数,它接受部分平铺并输出平铺中最左上方的未覆盖方块,如果不存在这样的方格则输出False。
函数number_of_tilings(partial_tiling)是递归定义的:如果uncovered_square(partial_tiling)输出False,则number_of_tilings(partial_tiling)= 1,因为partial_tiling实际上是一个正确的平铺。否则uncovered_square(partial_tiling)输出一些方形S.我们将一个多米诺骨牌水平放置在方形S(如果可能的话),从而生成一个新的部分平铺t_horizontal。同样我们定义t_vertical。最后我们计算number_of_tilings(t_horizontal)+ number_of_tilings(t_vertical)。
number_of_tilings的初始输入是一个$ N $ by $ N $棋盘,上面没有多米诺骨牌。
对于N = 2,4,6,该算法非常快速地给出了正确的答案,但是对于N> = 8,它非常慢(超指数时间)。
所以我的问题是存在其他可能的算法还是可以优化蛮力算法?
答案 0 :(得分:1)
这是一个非常简单的动态编程解决方案,运行在O(N * 2 ^ 2N)或更好:
生成填充第一行(小于2 ^ N)的所有可能方法。
由于多米诺骨牌只有2个方格长,因此其效果仅传播到第2行。第二行的可能配置少于2 ^ N。计算生成每一种方式的方式。
类似地,通过填充前2行产生第三行的< = 2 ^ N个配置,依此类推。给定通过填充前m行来生成每个配置的方法的数量,您可以通过在O(2 ^ 2N)时间或更好的时间内填充前M + 1行来计算生成每个配置的方式的数量。
对于通过填充前N-1行产生的每个配置,最多可以有1种方式填充最后一行。添加生成每个配置的方法,在最后一行只留下均匀的间隙,这就是你的答案。
在代码严密的好盒子上,我预计N = 16时间不到一分钟。 我可以想出一些让它快一点的方法,但没有任何东西可以在O(2 ^ N)
之下答案 1 :(得分:1)
这个问题已在文献中研究过,似乎并不容易和直接。例如看看
http://www.math.cmu.edu/~bwsulliv/domino-tilings.pdf
上面的链接提供了一个多项式时间算法来计算它。
实际上它首先将其转换为图形问题,即特殊图形类中的完美匹配数。然后定义该图的邻接矩阵,并计算该矩阵的永久性,该矩阵等于完美匹配的数量。
在一般图表中计算矩阵的永久性是很困难的。但是在这个特定的图形或平面图中,可以解决它。但这部分的想法并不是很直观。