我被问到编程测试解决了一个问题,我必须找到矩形图上每个节点到图上一组可能目的地之一的最短距离。我能够创建一个通过所有测试的解决方案,但我相当确定有更高效的算法。
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我正在寻找什么?我并不关心所有配对。
您可能指出的任何想法或参考资料?非常感谢。
答案 0 :(得分:2)
对于任意图形大小,具有任意数量的目标节点(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 neighbor
循环每个节点最多迭代4次,因为图形是矩形的。
这意味着内部if
条件将在 4n 附近执行,即这是 O(n)。根据使用的数据结构,数字可以 4n-4√n,因为边界节点具有较少的邻居,但这仍然是 O(n)。
请注意,如果目标节点(FGB)少于4个,则使用图形的矩形属性来计算距离会更快(尽管在大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 的值,可以选择要应用的方法。
答案 1 :(得分:2)
有一个简单的解决方案可以分两次使用。
传球是前进的,一排一排。对于每个节点,您将逐步评估距离上方左侧最近目标的距离。
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)
在记录新值的同时,您可以记录相应目标的位置。
(当邻居不存在时,按照惯例,距离是无限的。)
答案 2 :(得分:0)
回应@ yves-daoust(我知道我并不是想用一个全新的答案来回应其他答案,但这对于#34;对答案的响应来说太长了#34;对话框)。
所以整件事看起来像这样吗?
// 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)。是吗?