简短说明:
我正在尝试生成具有多米诺骨牌或换句话说具有2x1和1x2瓦片的正方形拼贴。
有时我的算法会以某种方式放置垂直图块,从而无法填充最后一行。
我的当前方法是用0初始化一个网格(例如8x8网格)。 我在网格中用1表示水平图块的左半部分,在网格中用2表示右半部分。
相应地,垂直图块的上半部分为3,下半部分为4。
然后我从左到右浏览网格的每一行,在其中放置0的图块是我所在的位置:
每当我放置一个图块(1或3)时,我也会相应地将相应的一半放置到网格的相邻空间中。假设我在(i,j)处放置1,然后在(i,j + 1)处放置2。
StoneMatrix = int[8][8];
for (int i = 0; i < StoneMatrix.length; i++) {
for (int j = 0; j < StoneMatrix.length; j++) {
if (StoneMatrix[i][j] != 0){
//field already set as a tile
continue;
}
if (i == StoneMatrix.length - 1) {
//bottom row
StoneMatrix[i][j] = 1;
StoneMatrix[i][j + 1] = 2;
continue;
}
if (j == StoneMatrix.length - 1) {
//right edge
StoneMatrix[i][j] = 3;
StoneMatrix[i + 1][j] = 4;
continue;
}
if (StoneMatrix[i][j + 1] != 0) {
//field to the right taken.
StoneMatrix[i][j] = 3;
StoneMatrix[i + 1][j] = 4;
continue;
}
StoneMatrix[i][j] = putOneOrThreeRandomly();
putCorrespondingAdjacentTile();
}
}
我觉得必须有一种简单的方法来生成这种平铺,但是我还找不到。 我正在寻找的要么是描述了这种生成算法的某个来源,要么是解决了我的错误的简单解决方案。
答案 0 :(得分:1)
使用 n
多米诺骨牌通过 m
棋盘创建任意 2x1
的随机最大平铺。当 n*m
为偶数时,平铺将是完美的。
考虑棋盘的白色和黑色方块。多米诺骨牌必须同时覆盖白色和黑色方块。因此,如果存在一些完美的拼贴,那么解决方案可以转化为如下图:每个棋格成为一个顶点,如果多米诺牌覆盖了两个相邻的拼贴,则这两个顶点是连接的。这将导致二部图(所有边都有一个白色和一个黑色顶点)和(最大)匹配图。
因此,给定任何大小的网格(或任何形状),如果我们能够解决二部图中的最大基数匹配问题,我们就可以将解决方案转换为多米诺平铺。
为了解决上述图形问题,将其转换为最大流问题,并与 Ford Fulkerson 一起解决。将源节点连接到所有白色瓷砖,将汇节点连接到所有黑色瓷砖。只有当它们是国际象棋网格上的邻居时,白色瓷砖才指向黑色瓷砖。用容量为 1 的所有边求解。节点之间利用的边表示将在那里放置多米诺骨牌。
考虑一个 2 行深、4 列宽的棋盘。白色方块是{0, 1, 2, 3},黑色方块是{4, 5, 6, 7}
+---+---+---+---+
| 0 | 4 | 1 | 5 |
+---+---+---+---+
| 6 | 2 | 7 | 3 |
+---+---+---+---+
现在假设我们有两个额外的节点,8
源节点和 9
接收器节点。然后找到最大流量的图表如下所示。请注意,所有边的容量为 1。
0: 4, 6
1: 4, 5, 7
2: 4, 6, 7
3: 5, 7
4: 9
5: 9
6: 9
7: 9
8: 0, 1, 2, 3
在运行 Ford-fulkerson 之后(使用随机 DFS 获得有趣的解决方案——如果您每次都想要无聊的逐行解决方案,请使用 BFS),我们可能会发现使用了以下边缘。请注意,涉及源/汇节点的边已被省略,因为它们对重建平铺没有用。
0-4
2-6
1-7
3-5
最后,这对应于下面的平铺
+-----+---+---+
| 0 4 | 1 | 5 |
+-----+ | |
| 6 2 | 7 | 3 |
+-----+---+---+
我还在此处用 Java 创建了一个概念证明:https://github.com/forsythe/domino_tiling。如果你想看到它的实际效果,这里有一个 16x16 的输出:
答案 1 :(得分:0)
每当我进入无法再正确填充网格的状态时,我通过将布尔值设置为true来“解决”该问题。
然后在生成方法的末尾,如果布尔值为false,则网格有效,或者如果布尔值为true,则重新启动该方法。我认为基本上是一个肮脏的“尝试和错误”。
那不是我想要的解决方案,但是它可行。所以我将这个问题保留。