如何解决查找图上距离N个节点的所有节点
您和几个朋友正在玩棋盘游戏。游戏的棋盘被布置在一个大的,互连的图形中,该图形具有许多循环。每个玩家都从棋盘上的不同位置开始。轮到您时,您可以在1到6个6面骰子之间滚动任何东西(换句话说,从1-36掷骰子)。您如何确定您可能会从当前位置单次转弯进入的每个空间? (例如:我掷出13个。找到板上距离我13个空格的所有点。)您只能向前移动,但可以环回以遍历小于掷骰子的净总数
示例:如果这是您的图形,并且从左上角开始滚动6,则可以向下,向右,向右,向上,向左,向左移动。但是,您不能向右,向左,向右,向左,向右,向左移动。
o---o---o---o---o
| | |
o---o---o---o
有没有比深度优先搜索更好的算法?
解决方法
您完全不需要遍历图形即可解决此问题。
图可以通过其邻接矩阵进行编码:矩阵M
使得M(i,j) = 1
(如果从节点i
到节点{{ 1}}和j
(如果没有优势)。
此矩阵具有超酷的属性:对于任何非负整数M(i,j) = 0
,k
(M**k
的{{1}}次幂,即 ie ,k
乘以自身M
倍)使得M
=从k
到(M**k)(i,j)
的不同步数。
如果i
,则可以以j
的精确度从节点(M**k)(i,j) > 0
到达节点i
。请注意,如果您确保每个节点都有自己的边缘 ie ,如果j
的对角线充满k
s,则可以完全M
个动作中到达的节点与最多1
个动作中可以到达的节点相同。
另请参阅:https://en.wikipedia.org/wiki/Adjacency_matrix#Matrix_powers
在大多数编程语言中,都有一些库可以非常有效地处理矩阵和矩阵运算,因此,将矩阵发挥功效可能比实际访问另一个图的节点快得多。
另一方面,如果图很大而k
小,而您只对一个起始节点感兴趣,那么计算k
可能比图遍历效率低,因为{{ 1}}回答了图形中每个节点的问题,而不仅仅是针对您感兴趣的起始节点。
但是,如果您对所有可能的起始节点都感兴趣,或者如果k
接近图的直径,那么计算M**k
很可能是最佳选择。
由于您可以绕圈子但不能直接回到您来自的节点的限制,实际上这是一个很有趣的问题。尤其是,您既不能做BFS或DFS来以较少的移动来修剪已经访问过的所有节点,也不可以巧妙地进行矩阵乘法。
相反,您可以使用DFS的变体,但是您必须同时跟踪可以到达某个节点的移动数量以及访问该节点时来自的节点,并且如果要访问,则只能修剪修剪之前曾经见过 exact 组合-如果您到达的节点较少,或者来自另一个节点,则不是这样。
Python的基本实现和示例:
def search(graph,start,moves):
stack = [(start,-1)]
distance = {i: set() for i in range(moves+1)}
while stack:
node,dist,prev = stack.pop()
if (node,prev) in distance[dist]: continue
distance[dist].add((node,prev))
if dist < moves:
stack.extend((x,dist+1,node) for x in graph[node] if x != prev)
return {node for (node,prev) in distance[moves]}
# 1---2---3---4---5
# | | |
# 6---7---8---9
g = {1: [2,6],2: [1,3],3: [2,4,8],4: [3,5,9],5: [4],6: [1,7],7: [6,8: [3,7,9: [4,8]}
print(search(g,1,13))
# {8,2,6}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。