我正在研究一个迷宫问题,其中迷宫以二维数组表示,因此如果一个元素是假的,那么方形就不可能穿过,反之亦然。我已经实现了一种求解方法,该方法以深度优先的方式递归地尝试遍历起点的所有相邻正方形,这样可以正常工作。
然而,我想尝试击败DFS算法,我有想法将迷宫简化为图形,(并且可能尝试为边缘分配权重)并在图形上执行DFS而不是每个迷宫中的单一广场。我遇到的问题是,我将迷宫变成虎斑的方式似乎非常低效。以下是将布尔矩阵转换为图形的方法概述:我从第0行开始,经过索引0,0到索引n,0,然后是0,1 .. n,1到n,n的每一行。编辑:澄清:我让迷宫中的x值先增加。然后我在下一段中垂直链接节点。
我会在矩阵中调用空方格中的真值。 *如果白板正方形位于板的边缘,我将创建一个名为Opening的Node类的新子类。我将保留对该节点的引用。继续向右,如果我击中十字路口或下一个方格是黑色,我在两者之间建立一个节点和一个边界。如果我从黑色方块步进到白色方块,并且如果右边的下一个方块不是黑色,我创建一个节点,然后在该节点和沿着该行的下一个节点之间形成边缘。
所有节点都被添加到节点列表中。然后,我遍历所有colomns从(0,0),(0,1),...,(0,n),(1,0),(1,1)..(1,n)。并在所有未被黑色方块分隔的节点之间建立边缘。
这感觉就像是一种非常昂贵的事情。我很想听听有关如何正确完成这项工作的任何建议。
F F F F F F F F F F F F F
T T F T T T T T T T T T F
F T F F F F F F F T F F F
F T T T F T T T F T F T F
F F F T F T F T F F F T F
F T F T F T F T T T T T F
F T F T F T F F F F F F F
F T T T F T T T T T T T F
F T F F F F F F F F F T F
F T F T T T T T T T T T F
F T F T F F F F F F F T F
F T T T F T T T T T T T T
F F F F F F F F F F F F F
会创建这些节点:
. . . . . . . . . . . . .
O O . O . . . . . O . O .
. . . . . . . . . . . . .
. O . O . O . O . . . . .
. . . . . . . . . . . . .
. . . . . . . O . . . O .
. . . . . . . . . . . . .
. O . O . O . . . . . O .
. . . . . . . . . . . . .
. . . O . . . . . . . O .
. . . . . . . . . . . . .
. O . O . O . . . . . O O
. . . . . . . . . . . . .
这并没有显示边缘,但也许你明白了。
答案 0 :(得分:1)
我有两个解决方案,其中一个已经实施。在我开始解释第一个算法之前,这里有一些算法依赖的假设:
<强> Assumtions 强>
T
或整个迷宫仅由不可行走的瓷砖F
组成。<强>算法强>
我将通过一个更简单的例子解释算法,仍然涉及许多重要案例。考虑以下由5行3列组成的迷宫:
可行走的瓷砖T
为绿色,而墙砖[{1}}为蓝色。
算法的第一阶段从(x,y)=(0,0)开始,通过访问顺时针移动的寄宿生瓷砖来搜索可步行的边界瓷砖 。它更喜欢具有少于或多于2个开放边缘的可步行瓷砖。 开放边是我们知道一个节点但不是另一个伙伴节点的边缘。
从tile(x,y)=(0,0)开始,找到一个 walkable 节点,其中有2个开放边(表示为白色箭头)。它记住候选节点(由橙色圆圈表示)并继续,希望找到如上所述的优选节点。
在步骤5,它找到由图块(2,2)表示的具有3个开放边缘的优选节点。它将节点标记为F
(表示为带有白色或灰色背景的圆圈)并终止第一阶段。
第二阶段将选择一个任意unprocessed
节点并通过确定开放边的伙伴节点来处理它,直到不再有unprocessed
节点存在。之后,它会将节点标记为unprocessed
。确定伙伴节点可能会导致将其他节点标记为processed
。
可供选择的唯一unprocessed
节点是第一阶段中找到的(2,2)边界节点。算法选择它(由具有灰色背景的圆圈表示)。任意选择的开放边表示为灰色箭头(在我们的例子中指向南方)。
现在,算法通过沿着unprocessed
切片移动来搜索伙伴节点,直到找到一个节点(一个具有少于或多于两个边的图块或者是算法启动的图块)在)。
在我们的例子中,算法在步骤6中找到由步行瓦片(0,2)表示的伙伴节点。由于此节点既未标记为walkable
也未标记为processed
,因此将节点标记为unprocessed
(由具有白色背景的圆圈表示)。 开放边现在是unprocessed
(用黑色箭头表示)到伙伴节点,反之亦然。
算法继续选择所选节点的开放边,直到所有开放边链接到其伙伴节点。在我们的示例中,下一个任意选择的开放边指向西方。
算法沿着可行走的区块移动并找到由区块(0,2)表示的伙伴节点,它已经在之前找到并且已经标记为linked
。因此,它链接两个节点的开放边,并继续指向北的最后一个开放边。
它找到与之前相同的节点,并链接最后一个开放边。现在,(2,2)处的选定节点不再有开放边,因此算法将其标记为unprocessed
(由具有绿色背景的圆圈表示)。
该算法继续选择任意processed
节点,找到由(0,2)处的图块表示的唯一可用节点。但由于此节点没有任何开放边,因此它会立即将其标记为unprocessed
并继续。
不再有processed
个节点可用,因此算法终止。
适用于OP示例
如果应用于您提供的示例,则生成的图形会小得多,而不会丢失有关导航迷宫的任何信息。让我们看看你的图表(我必须完成,因为缺少一些节点):
左侧的图片显示了您的示例和建议算法生成的图表。右边的图片显示了我描述的算法找不到的节点,因为它们可以在不丢失任何导航信息的情况下进行优化。它们要么被边缘取代要么被完全消除。结果如下所示:
左边的图片显示了替换,而右边的图片只是它的压缩版本。图形从25个节点减少到8个节点,从23个减少到7个边缘。总体而言,减少了2/3个节点和边缘。
有趣的角落案例
当我实现算法时,我发现了一些我想与你分享的有趣角落案例。我会匆匆通过算法来保持图像小。我希望你已经掌握了算法的工作原理。