[英]Shortest Distances To One Of Multiple Potential Destinations
在编程测试中要求我解决一个问题,我必须找到从矩形图上的每个节点到图上一组可能的目标之一的最短距离。 我能够创建一个通过所有测试的解决方案,但我可以肯定的是,那里有一个更有效的算法。
C11--C12--C13--C14
| | | |
FGB--C22--C23--C24
| | | |
C31--C32--C33--C34
| | | |
C41--FGB--C43--C44
| | | |
C51--C52--C53--C54
| | | |
C61--C62--C63--FGB
因此,例如,在上图中,说每个“ FGB”代表五个人(因为它很美味)。 每个“ Cxx”代表一个客户。 本质上是,“每个客户离最近的五个人有多远?” 因此C11距离1,C12距离2,依此类推。所有边的权重均为1。
我在寻找Floyd-Warshall吗? 我不太在乎所有的配对。
您可能会指出我任何想法或参考资料吗? 非常感激。
对于具有任意数量的目标节点(FGB)的任意图形大小,以下BFS算法将是最有效的:
nodes = set of all nodes
currentNodes = set of target nodes (FGB)
for each node in nodes:
dist[node] = infinity
for each node in currentNodes:
dist[node] = 0
while currentNodes is not empty:
newNodes := []
for each node in currentNodes:
for each neighbor of node:
if dist[neighbor] > dist[node] + 1 then:
dist[neighbor] := dist[node] + 1
newNodes.add(neighbor)
currentNodes := newNodes
for each node
循环总共将只for each node
访问一次。
给定该图为矩形for each neighbor
循环的for each neighbor
节点最多将迭代4次。
这意味着内部if
条件将执行近4n次,即O(n) 。 取决于所使用的数据结构,该数目可以是4n-4√n,因为边界节点的邻居较少,但这仍然是O(n) 。
请注意,如果您的目标节点(FGB)少于4个,则使用图形的矩形属性计算距离会更快(尽管对于big-O而言并不重要)。 您可以使用以下公式执行此操作,其中m是目标节点(FGB)的数量:
dist[node at [i,j]] := min( abs(i-FGB[0].column)+abs(j-FGB[0].row),
abs(i-FGB[1].column)+abs(j-FGB[1].row),
...
abs(i-FGB[m-1].column)+abs(j-FGB[m-1].row)
)
这具有O(nm)的时间复杂度,对于m限制为某个常数,该时间复杂度仍为O(n),并且可能比更通用的解决方案更快。
一种算法可以利用这一点,并且根据m的值,可以选择要应用的方法。
有一个简单的解决方案可以通过两遍。
点火通过是逐行的。 对于每个节点,您将逐步评估到上方左侧最近的目标的距离。
D(node)= if target node => 0 else min(D(left neighbor) + 1, D(top neighbor) + 1)
第二遍是后退。 最终距离评估为
D(node)= min(D(node), D(right neighbor) + 1, D(bottom neighbor) + 1)
记录新值的同时,您可以记录相应目标的位置。
(如果不存在邻居,则按照惯例,距离是无限的。)
响应@ yves-daoust(我知道我不应该用一个全新的答案来回答其他答案,但这对于“响应回答”对话框来说太长了)。
所以整个事情看起来像这样吗?
// O(n)
for each node:
set node distance to infinity
// O(m)
for each FGB in FGB coordinate list
directly set corresponding node distance to infinity
// O(n)
for each i in row
for each j in column
if left and up exist
set node(i,j) to min(node(i,j), left+1, up+1)
else if left exists
set node(i,j) to min(node(i,j), left+1)
else if up exists
set node(i,j) to min(node(i,j), up+1)
// O(n)
for each i in row (reverse)
for each j in column (reverse)
if right and down exist
set node(i,j) to min(node(i,j), right+1, down+1)
else if right exists
set node(i,j) to min(node(i,j), right+1)
else if down exists
set node(i,j) to min(node(i,j), down+1)
整个事情是O(3n + m)= O(n + m)。 那正确吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.