我最近出现在一个求职面试中,我被问到流行的大麻问题,其中有一个由二维阵列代表的迷宫,包含开放路径和墙壁的0和1我们必须分别打印最短的路径。
我使用回溯解决了问题,并打印了所有可能的路径。
然后面试官提高了韧性水平,并要求我用一个新的条件解决同样的问题,老鼠可以绊倒" K"用户输入K的墙数。
现在我尝试了很多,但是如果允许绊倒K墙,我无法弄清楚如何找到最短路径。我想是否可以通过动态编程解决但最终无法实现它。 / p>
面试官也没有透露解决方案。 任何人都可以解释这个问题的解决方案吗?
答案 0 :(得分:2)
您可以使用breadth-first search解决此问题。
如果你还不熟悉它,你可能想要阅读上面链接的基本BFS算法,因为下面很大程度上是基于此。
对于每个单元格,我们需要存储我们经过的墙壁数量才能到达该单元格 - 请调用此walls
。
从包含我们的起始单元格的队列开始。
让起始单元格walls
为0
。
重复设置当前单元格等于队列的第一个元素(我们删除)。
如果当前单元格是目标单元格,请打印出路径并完成。
如果当前单元格是墙,请将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个墙的路径最终需要通过太多的墙。