Algorithm 回溯-如何解决“回溯”的这种变体;迷宫里的老鼠;?

Algorithm 回溯-如何解决“回溯”的这种变体;迷宫里的老鼠;?,algorithm,recursion,backtracking,Algorithm,Recursion,Backtracking,我最近参加了一次工作面试,在面试中,我被问到了一个迷宫问题中流行的老鼠。在这个问题中,有一个迷宫由一个二维数组表示,该数组分别包含开放路径和墙壁的0和1,我们必须打印最短路径 我用回溯法解决了这个问题,还打印了所有可能的路径 但是面试官提高了我的强硬程度,让我用一个新的条件来解决同样的问题,在这个条件下,老鼠可以绊倒“K”个由用户输入K的墙 现在我做了很多尝试,但是没有弄清楚如果允许绊倒K墙,如何找到最短路径。我想是否可以通过动态规划来解决这个问题,但最终无法实现 采访者也没有透露解决方案。 有

我最近参加了一次工作面试,在面试中,我被问到了一个迷宫问题中流行的老鼠。在这个问题中,有一个迷宫由一个二维数组表示,该数组分别包含开放路径和墙壁的0和1,我们必须打印最短路径

我用回溯法解决了这个问题,还打印了所有可能的路径

但是面试官提高了我的强硬程度,让我用一个新的条件来解决同样的问题,在这个条件下,老鼠可以绊倒“K”个由用户输入K的墙

现在我做了很多尝试,但是没有弄清楚如果允许绊倒K墙,如何找到最短路径。我想是否可以通过动态规划来解决这个问题,但最终无法实现

采访者也没有透露解决方案。 有人能解释一下这个问题的解决方法吗?

你可以使用

如果你还不太熟悉的话,你可能想从阅读上面链接的基本BFS算法开始,因为下面的大部分都是基于此

  • 对于每个单元格,我们需要存储到达该单元格所经过的墙的数量-称之为
    walls

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

  • 让起始单元格的
    0

  • 重复将当前单元格设置为队列的第一个元素(我们将其删除)

    • 如果当前单元格是目标单元格,打印出路径,我们就完成了

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

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

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

      如果未初始化
      neighbor.walls
      (表示我们以前没有去过那里)或
      current.walls
      (表示新路径的墙较少),
      然后设置
      neighbor.wall=current.walls
      并将
      neighbor
      添加到队列中

要真正能够打印出路径,请创建一个映射,将任何带有
墙的单元格映射到我们从中到达的单元格(它是
)。简单地将一个单元格映射到前一个单元格是不可行的,因为如果路径上的前一个单元格的值小于
K
,则可以覆盖该路径上的前一个单元格

您还可以存储整个路径,但这样的效率要低得多

时间复杂度为
O(行*列*K)
,空间复杂度为
O(行*列)


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

如果我们有一个足够大的
K
,我们只需穿过两堵墙(绿色路径)两步就可以到达右上角的单元格

如果
K
不够大,我们需要绕过(蓝色路径),这将需要4步


因此,我们会进行常规BFS,但也会记录每个单元格穿过的墙数,因此如果我们在遍历后到达右上角的单元格,我们会看到它以前是通过穿过两个墙(而不是当前的0)到达的,因此,如果使用两堵墙的路径最终需要穿过太多的墙,我们将继续从那里走下去。

通过“绊倒”墙,你的意思是移动或移除墙壁?这是一个可以用Dijkstra解决的变体,其中每个节点还存储哪些墙壁已被移除。通过潜在地穿透到你已经去过的地方,你不是在浪费穿透吗?难道你不应该等到你画出了迷宫中你能正常到达的部分,然后决定从何处突破?@Dukeling感谢您的解决方案。请您解释一下以下原因:如果neighbor.walls已初始化且为当前版本。walls=
,而不是