【问题标题】:Efficient way to turn a boolean matrix into a graph structure?将布尔矩阵转换为图形结构的有效方法?
【发布时间】:2017-05-19 14:18:57
【问题描述】:

我正在处理一个迷宫问题,其中迷宫以二维数组表示,因此如果元素为假,则该正方形无法通过,反之亦然。我已经实现了一种求解方法,它递归地尝试以深度优先的方式遍历起点的所有相邻方格,它应该可以正常工作。

然而,我想尝试击败 DFS 算法,并且我有将迷宫简化为图形的想法(并可能尝试为边缘分配权重)并在图形上进行 DFS,而不是每个迷宫中的单个正方形。我遇到的问题是,我把迷宫变成抓斗的方式似乎效率很低。这是将布尔矩阵转换为图形的方法的概述:

我从第 0 行开始,遍历从索引 0, 0 到索引 n,0 的每一行,然后是 0,1 .. n, 1 直到 n,n。编辑:澄清:我让迷宫沿线的 x 值首先增加。然后我在下一段中垂直链接节点。

我将把矩阵中的真实值称为开放正方形。 *如果棋盘边缘有一个白色方块,我会创建一个新的节点类的子类,称为Opening。我将保留对该节点的引用。继续向右,如果我遇到十字路口或下一个方块是黑色的,我会在两者之间创建一个节点和一个端点。如果我从一个黑色方块走到一个白色方块,并且如果右边的下一个方块不是黑色的,我会创建一个节点,并在该节点和沿行的下一个节点之间创建一条边。

所有节点都被添加到节点列表中。然后,我从 (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
. . . . . . . . . . . . .

这并没有显示边缘,但也许你明白了。

【问题讨论】:

  • 我有一个方法,我回家后会尝试...今天是星期五:p

标签: java graph maze


【解决方案1】:

我想到了两种解决方案,其中一种已经实施。在我开始解释第一个算法之前,这里有一些算法依赖的假设:

假设

  1. 迷宫在以下方面是最小的:要么迷宫的边界瓷砖包含可步行的瓷砖T,要么整个迷宫仅由不可步行的瓷砖F组成。
  2. 迷宫定义了一个矩形,换句话说:迷宫的每一行都有相同数量的列。

算法

我将通过一个更简单的例子来解释这个算法,仍然涉及到许多重要的案例。考虑以下由 5 行 3 列组成的迷宫:

可步行的瓷砖T 是绿色的,而墙砖F 是蓝色的。

算法的第一阶段从 (x, y) = (0, 0) 开始,通过顺时针移动访问 boarder tile 来寻找可步行的boarder tile .它更喜欢具有少于或多于 2 个开放边缘的可行走瓷砖。 开放边是我们知道一个节点但不知道另一个伙伴节点的边。

它从 tile (x, y) = (0, 0) 开始,找到一个 walkable 节点,它有 2 个 开放边(表示为白色箭头)。它记住候选节点(由橙色圆圈表示)并继续,希望找到如上所述的优选节点。

在第 5 步,它找到了一个由图块 (2, 2) 表示的优选节点,具有 3 个开放边。它将节点标记为unprocessed(表示为具有白色或灰色背景的圆圈)并终止第一阶段。

第二阶段将选择一个任意的unprocessed 节点并对其进行处理,方法是确定开放边伙伴节点,直到不再存在unprocessed 节点。之后它会将节点标记为processed。确定伙伴节点可能会导致将其他节点标记为unprocessed

唯一可以选择的unprocessed 节点是在第一阶段找到的 (2, 2) 处的 边界节点。算法选择它(由一个灰色背景的圆圈表示)。任意选择的开放边表示为灰色箭头(在我们的例子中指向南方)。

现在算法搜索伙伴节点,沿着walkable瓦片移动直到找到一个节点(一个瓦片具有少于或多于2条边,或者是算法开始的瓦片) .

在我们的例子中,算法在步骤 6 中找到 伙伴节点,该节点由可行走的瓦片 (0, 2) 表示。因为该节点既没有标记为processed,也没有标记为unprocessed,因此它将该节点标记为unprocessed(由具有白色背景的圆圈表示)。 开放边现在是linked(用黑色箭头表示)到它的伙伴节点,反之亦然。

算法继续挑选所选节点的开放边,直到所有开放边都链接到它们的伙伴节点。在我们的示例中,下一个任意选取的开放边缘指向西。

算法沿着可行走的瓦片移动并找到由瓦片 (0, 2) 表示的 伙伴节点,它之前已经找到并标记为 unprocessed。因此,它将两个节点的开放边链接起来,并继续最后一个开放边指向北方。

它找到与之前相同的节点并链接最后一个开放边。现在 (2, 2) 处的选定节点不再有开放边,因此算法将其标记为processed(由具有绿色背景的圆圈表示)。

该算法继续选择任意unprocessed 节点,找到由位于 (0, 2) 处的图块表示的唯一可用节点。但由于该节点没有任何开放边,它立即将其标记为processed 并继续。

没有更多可用的unprocessed 节点,因此算法终止。

应用于 OP 示例

如果应用于您提供的示例,生成的图表会小得多,而不会丢失任何有关在迷宫中导航的信息。让我们看看您的图表(我必须完成,因为缺少一些节点):

左边的图片显示了您的示例和建议的算法产生的图表。右图显示了我描述的算法找不到的节点,因为它们可能会被优化掉而不会丢失任何导航信息。它们要么被边缘取代,要么被完全消除。结果如下图:

左边的图片显示替换,而右边的图片只是它的压缩版本。该图从 25 个节点减少到 8 个节点,从 23 个减少到 7 个边。总体上减少了 2/3 的节点和边。

有趣的角落案例

在实现算法时,我发现了一些有趣的极端案例,我想与您分享。我将快速完成算法以保持图像小。我希望你已经了解了算法的工作原理。

  1. 单个可行走 tile,因此完全没有边缘:

  1. 只有边界地砖可以步行

  1. 所有图块都可步行

  1. 最好的边框瓷砖是单边的:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多