我正在寻找一种解决此问题的方法,其中您必须用L形的三块瓷砖填充n * m(n,m <= 8)块矩阵。磁贴不能以任何方式彼此叠置。
我并不一定要寻找完整的答案,而只是提示如何使用它。
答案 0 :(得分:1)
我使用graph problem recursive算法和backtracking算法解决了memoization问题。我的解决方案不是特别快,并且需要一分钟左右的时间来解决9x12网格,但对于您所问的8x8网格应该足够了(在9x9上大约需要一秒钟)。对于7x7和8x8网格,没有解决方案,因为它们不能被triomino大小3整除。
策略是从网格的一个角落开始,逐格移动,在合法的情况下尝试放置每个块,从而有条不紊地探索解决方案空间。
如果放置一个积木是合法的,但是在网格中创建了一个无法填充的气穴,则卸下该积木;我们知道提前没有解决该状态的方法,可以放弃探索它的孩子。例如,在3x6网格上,
abb.c.
aabcc.
......
是无法解决的。
一旦达到所有单元格都已填充的状态,我们就可以向其父状态报告1个解的计数。这是一个解决3x6网格的示例:
aaccee
abcdef
bbddff
如果每个可能的块都放置在某个位置,请回溯,在此过程中将解决方案计数报告给父状态,并探索尚未探索的任何状态。
就记忆而言,如果瓦片的某种排列方式使得它们覆盖完全相同的坐标,则称任意两个网格状态等效。例如:
aacc..
abdc..
bbdd..
和
aacc..
bacd..
bbdd..
即使通过不同的图块放置达到了两个状态,也认为是等效的。两种状态都具有相同的子结构,因此计算一种状态的解决方案数量就足够了。将其添加到备忘录中,如果再次达到状态,我们只需报告备忘录中的解决方案数量即可,而无需重新计算所有内容。
我的程序在3x6网格上报告了8个解决方案:
正如我提到的那样,我的Python解决方案不是快速的,也不是优化的。不到一秒钟即可解决9x12网格。除了进行大型优化外,我在实现过程中还忽略了一些基本的东西。例如,我为每个图块位置复制了整个网格;在单个网格上添加/删除磁贴将是一个容易的改进。我也没有检查网格中无法解决的间隙,可以在动画中看到。
解决问题后,请务必四处寻找人们提出的令人鼓舞的解决方案。我不想为此付出更多!
答案 1 :(得分:0)
有一个技巧可用于许多递归枚举问题。无论采用哪种方式,都可以定义确定性的过程,以从非空的部分解决方案中删除一个部分。然后,递归枚举朝相反的方向工作,从空解中构建可能的解,但是每次放置一块时,同一块必须是确定性过程中要删除的那个。
如果在开始枚举之前验证板的尺寸可以被三分之一,那么时间限制就不会有问题。