Algorithm 采访:寻找到少数元素的最短路径

Algorithm 采访:寻找到少数元素的最短路径,algorithm,time-complexity,shortest-path,Algorithm,Time Complexity,Shortest Path,有一个博物馆组织为NxN室。有些房间上锁,无法进入。其他房间是开放的,有些房间有警卫。警卫只能通过开放的房间,也只能在博物馆内,从北、南、东、西移动。对于每个房间,找到与警卫的最短距离。您的算法的时间复杂度是多少?您只需将该博物馆视为一个图形,然后使用Dijikstra算法即可 您可以在给定页面上讨论复杂性。您可以在本系列文章中找到Dijkstra的最短路径算法: 作为一个开始,考虑一个比较幼稚的方法。 将每个防护装置G作为房间集中的顶点,R=N*N,相邻房间(边)之间的可能路径E 如果必

有一个博物馆组织为NxN室。有些房间上锁,无法进入。其他房间是开放的,有些房间有警卫。警卫只能通过开放的房间,也只能在博物馆内,从北、南、东、西移动。对于每个房间,找到与警卫的最短距离。您的算法的时间复杂度是多少?

您只需将该博物馆视为一个图形,然后使用Dijikstra算法即可


您可以在给定页面上讨论复杂性。

您可以在本系列文章中找到Dijkstra的最短路径算法:


作为一个开始,考虑一个比较幼稚的方法。

将每个防护装置G作为房间集中的顶点,R=N*N,相邻房间(边)之间的可能路径E

如果必须知道所有房间的最小距离,则每个警卫到每个房间的BFS

这需要时间
G*(R+E)
,或者类似
G*(N*N+E)
,或者
G*(N*N)

这当然可以通过记忆优化,因为每个BFS将重复计算已经完成的子树。根据房间的配置,这可以大大降低上述时间复杂性的G。不过,我相信一定有比这更好的方法。

图形解决方案 每个房间都是一个节点 只有门开着的房间之间才有边缘 使用Floyd–Warshall算法,然后检查每个房间和每个警卫之间的最小距离

房间数-R=N^2

警卫人数-G

时间复杂度为O(R^3+R*G)=O(R^3)=O(N^6)


R^3对于Floyd–Warshall

我假设一个函数edgeCost(I,j),它返回从房间I到房间j的转换成本(如果没有,则为无穷大,否则为1)。此外,edgeCost(i,i)=0,并且没有负循环。设R为房间数(在您的情况下,R=N^2):


或者您可能知道,Floyd Warshall算法(所有对最短路径),时间复杂度为O(| R |^3)。

如果我们使用人工源和从源到每个防护的零长度边来扩充博物馆图,那么单源最短路径树,可通过BFS(未加权)/Dijkstra(加权)在时间内计算(n2+g),给出每个房间到最近警卫的距离。

有一个队列,其条目中的每个条目都包含一个正方形和一个整数的地址。将所有警卫的位置放在一个队列中,每个位置都标记有整数“0”。每个正方形都应该有一个数字的空间,并且它们最初都应该为空


然后,只要队列中有东西,就从队列中拉出一个条目,并检查有问题的方块是否有标记的值。如果有,就忽略该队列条目并继续下一个。否则,用队列中的值标记方块,并将所有可直接到达的相邻方块放在队列中,值为1 hi大于当前条目的值(因此,当第一批方块中的每一个从队列中拉出时,它们将得到值“1”)。每个方块为空时只会访问一次,每个访问过的方块最多会导致四个方块排队,因此通过队列的项目总数将是方块数的四倍,再加上警卫的数量。通过检查每个方块,可以很容易地将该值减少一个常数因子,以查看是否在将其添加到队列之前,它是空白的;这不会消除所有冗余队列,但会消除一些。

以下是最佳解决方案的摘要(O(N^2)),由IVladthrowayacct提到。出于某种原因,他们的声音没有被听到:)

将NxN网格视为一个图形,其中节点表示房间,边表示相邻房间之间的门。所有边的权重均为1。一组节点U被标记为“受保护的房间”

其想法是使用BFS遍历,该遍历从连接到所有受保护房间的新节点开始,并从v0开始以递增的距离顺序扫描房间。每次访问一个节点时,为到达该节点而采取的步骤数表示与受保护房间的距离,并且由于路径扩展顺序,该距离保证最小:

Add an artificial node v0 and connect it to all nodes in U
Create a simple queue Q, that stores pairs <node, dist>
Q.enqueue(<v0, -1>) 
Create a hash set S, that contains all visited nodes
S.add(v0)
while not Q.isEmpty() {
    pathTail := Q.dequeue()
    output distance pathTail.dist for node pathTail.node
    for all neighbours v of pathTail.node
        if not S.contains(v)
            Q.add(<v, pathTail.dist + 1>)

    S.add(pathTail.node)

}
添加一个人工节点v0并将其连接到U中的所有节点
创建一个简单的队列Q,用于存储对
Q.排队()
创建包含所有访问节点的哈希集S
S.add(v0)
而不是Q.isEmpty(){
路径尾:=Q.dequeue()
节点pathTail.node的输出距离pathTail.dist
对于pathTail.node的所有邻居v
如果不是,则S.包含(v)
Q.添加()
S.add(pathTail.node)
}
复杂性分析

注意,图是平面的,所以我们有| V |+| E |=O(| V |)。因此,该BFS在O(| V |)=O(N^2)时间内运行


事实上,我们对边的权重是一致的,这使得事情变得简单;保证队列具有单调的距离值。以dijkstra为例,边的权重可能不同,因此需要优先级队列,这会影响时间复杂度。这里提出的相同问题是,房间之间的重量不同,这需要O(NNlog N)时间。

我们为什么要回答这个问题?我们不是申请这份工作的人。这就是这个网站的全部内容,帮助人们解答问题,如果你不知道答案,我也可以。你的意思是“访问者只能向北、向南、向东和向西移动…”吗+1,这比过度杀戮的dijkstra,尤其是roy floyd建议的解决方案要好得多。在将所有防护插入队列后,通过运行基于队列的BFS,您可以将此问题归结为
O(N^2)
。您不必为每个guard.E=O(NN)重新运行BFS,因为每个顶点最多贡献4条边。因此,复杂性公式可以简化为O(GN*N)。实际上,房间的数量是
N^2
而不是
N
。我是
Add an artificial node v0 and connect it to all nodes in U
Create a simple queue Q, that stores pairs <node, dist>
Q.enqueue(<v0, -1>) 
Create a hash set S, that contains all visited nodes
S.add(v0)
while not Q.isEmpty() {
    pathTail := Q.dequeue()
    output distance pathTail.dist for node pathTail.node
    for all neighbours v of pathTail.node
        if not S.contains(v)
            Q.add(<v, pathTail.dist + 1>)

    S.add(pathTail.node)

}