将布尔矩阵转换为图形结构的有效方法?

时间:2017-05-19 14:18:58

标签: java graph maze

我正在研究一个迷宫问题,其中迷宫以二维数组表示,因此如果一个元素是假的,那么方形就不可能穿过,反之亦然。我已经实现了一种求解方法,该方法以深度优先的方式递归地尝试遍历起点的所有相邻正方形,这样可以正常工作。

然而,我想尝试击败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
. . . . . . . . . . . . .

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

1 个答案:

答案 0 :(得分:1)

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

<强> Assumtions

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

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

    enter image description here

    可行走的瓷砖T为绿色,而墙砖[{1}}为蓝色。

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

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

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

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

    enter image description here

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

    现在,算法通过沿着unprocessed切片移动来搜索伙伴节点,直到找到一个节点(一个具有少于或多于两个边的图块或者是算法启动的图块)在)。

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

    enter image description here

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

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

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

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

    不再有processed个节点可用,因此算法终止。

    适用于OP示例

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

    enter image description here

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

    enter image description here

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

    有趣的角落案例

    当我实现算法时,我发现了一些我想与你分享的有趣角落案例。我会匆匆通过算法来保持图像小。我希望你已经掌握了算法的工作原理。

    1. 单个 walkable 磁贴,因此根本没有边缘:
    2. enter image description here

      1. 只有边框瓷砖 walkable
      2. enter image description here

        1. 所有图块都是 walkable
        2. enter image description here

          1. 优选的边框瓷砖有单边:
          2. enter image description here