Algorithm 回溯-如何解决“回溯”的这种变体;迷宫里的老鼠;?
我最近参加了一次工作面试,在面试中,我被问到了一个迷宫问题中流行的老鼠。在这个问题中,有一个迷宫由一个二维数组表示,该数组分别包含开放路径和墙壁的0和1,我们必须打印最短路径 我用回溯法解决了这个问题,还打印了所有可能的路径 但是面试官提高了我的强硬程度,让我用一个新的条件来解决同样的问题,在这个条件下,老鼠可以绊倒“K”个由用户输入K的墙 现在我做了很多尝试,但是没有弄清楚如果允许绊倒K墙,如何找到最短路径。我想是否可以通过动态规划来解决这个问题,但最终无法实现 采访者也没有透露解决方案。 有人能解释一下这个问题的解决方法吗?你可以使用 如果你还不太熟悉的话,你可能想从阅读上面链接的基本BFS算法开始,因为下面的大部分都是基于此Algorithm 回溯-如何解决“回溯”的这种变体;迷宫里的老鼠;?,algorithm,recursion,backtracking,Algorithm,Recursion,Backtracking,我最近参加了一次工作面试,在面试中,我被问到了一个迷宫问题中流行的老鼠。在这个问题中,有一个迷宫由一个二维数组表示,该数组分别包含开放路径和墙壁的0和1,我们必须打印最短路径 我用回溯法解决了这个问题,还打印了所有可能的路径 但是面试官提高了我的强硬程度,让我用一个新的条件来解决同样的问题,在这个条件下,老鼠可以绊倒“K”个由用户输入K的墙 现在我做了很多尝试,但是没有弄清楚如果允许绊倒K墙,如何找到最短路径。我想是否可以通过动态规划来解决这个问题,但最终无法实现 采访者也没有透露解决方案。 有
- 对于每个单元格,我们需要存储到达该单元格所经过的墙的数量-称之为
walls
- 从包含起始单元格的队列开始
- 让起始单元格的
墙
为
0
- 重复将当前单元格设置为队列的第一个元素(我们将其删除)
- 如果当前单元格是目标单元格,打印出路径,我们就完成了
- 如果当前单元格是墙,则将
增加1current.walls
- 如果
,则不执行任何操作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=
,而不是