回溯 - 如何在迷宫中解决这种变种?#34;?

时间:2017-08-04 20:53:25

标签: algorithm recursion backtracking

我最近出现在一个求职面试中,我被问到流行的大麻问题,其中有一个由二维阵列代表的迷宫,包含开放路径和墙壁的0和1我们必须分别打印最短的路径。

我使用回溯解决了问题,并打印了所有可能的路径。

然后面试官提高了韧性水平,并要求我用一个新的条件解决同样的问题,老鼠可以绊倒" K"用户输入K的墙数。

现在我尝试了很多,但是如果允许绊倒K墙,我无法弄清楚如何找到最短路径。我想是否可以通过动态编程解决但最终无法实现它。 / p>

面试官也没有透露解决方案。 任何人都可以解释这个问题的解决方案吗?

1 个答案:

答案 0 :(得分:2)

您可以使用breadth-first search解决此问题。

如果你还不熟悉它,你可能想要阅读上面链接的基本BFS算法,因为下面很大程度上是基于此。

  • 对于每个单元格,我们需要存储我们经过的墙壁数量才能到达该单元格 - 请调用此walls

  • 从包含我们的起始单元格的队列开始。

  • 让起始单元格walls0

  • 重复设置当前单元格等于队列的第一个元素(我们删除)。

    • 如果当前单元格是目标单元格,请打印出路径并完成。

    • 如果当前单元格是墙,请将current.walls增加1。

    • 如果current.walls > K,则不执行任何操作。

    • 对于每个邻居:(墙壁和开放的单元格)

      如果neighbour.walls未初始化(意味着我们以前没有在那里)或current.walls < neighbour.walls(意味着新路径的墙壁较少), 然后设置neighbour.wall = current.walls并将neighbour添加到队列中。

要实际能够打印出路径,请创建一个地图,将其walls的任何单元格映射到我们来自的单元格(以及walls)。简单地将单元格映射到前一个单元格是不行的,因为如果路径上的前一个单元格具有较低的K值,则可以覆盖它。

您也可以存储整个路径,但效率低得多。

时间复杂度为O(rows*columns*K),空间复杂度为O(rows*columns)

这里的许多复杂性是由于需要处理这样的场景:
(你可以想象这是更大网格的一部分)

如果我们有足够大的K,我们可以穿过两面墙(绿色路径)并以两个动作到达右上角的单元格。

如果K不够大,我们需要四处走动(蓝色路径),这将需要4次移动。

因此,我们会定期进行BFS,但也要记录每个细胞经过多少个墙壁,所以如果我们在四处走动后到达右上角的细胞,我们会看到之前达到的通过穿过2个墙(而不是当前的0),因此我们继续从那里开始,以防使用2个墙的路径最终需要通过太多的墙。