我将游戏板上的路径存储在字典中,格式如下:
{1: [2,3,4], 2: [1,3,5], 3: [1,2,4], ...}
这意味着如果您在空间1上,则可以移动到空格2,3或4,依此类推。每个键都链接到列表中的至少两个值;许多人有四个或更多。董事会共有199个空间。值得注意的是,有时你可能会跳过一个空格,所以... ...
{1:[2,3,4], 2:[3]}
...你可以去1 - > 2 - > 3,或者你可以去1 - > 3。
我正在寻找一种算法来找到任意两个方格之间的最短距离。显而易见的想法是查找起始空间的键,然后取出列表中的第一个数字,查找可能的空格,依此类推,当它到达之前看到的数字时停止并返回到上一个列表或最终方格(如果它到达结果方格则存储路径和距离,在完成后进行比较)。
但是,我对如何开始实现这一点知之甚少。 (如果只有两个步骤,我会使用嵌套循环,但显然这在这里不起作用,因为我不知道它可能会有多少级别。)欢迎涉及其他数据结构的更好的解决方案或优化;我将数据存储在类似于该字典的CSV文件中,因此如果效果更好,我可以轻松将其转换为其他内容。
这是我正在使用的电路板图片的链接: http://goo.gl/Rasq6
编辑:好的,我正在尝试实现Dijkstra的算法。这就是我所拥有的: 1 movedict, transdict = boardstruct.prepare_board()
2
3 source = 87
4 dest = 88
5
6 dist = {}
7 prev = {}
8 for v in movedict.keys():
9 dist[v] = float('inf')
10 prev[v] = None
11
12 dist[source] = 0
13 q = movedict.keys()
14
15 while q:
16 smallest = float('inf')
17 for i in q:
18 dist_to = dist[i]
19 if dist_to < smallest:
20 smallest = dist_to
21 print smallest
22 u = q.pop(smallest)
23 print u
24
25 if dist[u] == float('inf'):
26 break
27
28 for v in movedict[u]:
29 alt = dist[u] + 1 # distance = flat 1
30 if alt < dist[v]:
31 dist[v] = alt
32 prev[v] = u
33 # reorder queue?
(21和23是我忘记删除的调试语句)
我正在使用维基百科的伪代码(http://en.wikipedia.org/wiki/Dijkstra's_algorithm#Pseudocode),因为我找不到任何符合我所需要的数据格式的现有实现(每一步都有固定的成本,所以距离不会存储在任何地方。)
我知道我需要在最后重新排序队列,但我不确定如何。我也不明白第25和26行是什么(评论说“所有剩余的顶点都是从源头无法访问的” - 这是否只是让它在保证已经找到最佳路径时不再运行?)。我可能也搞砸了别的东西,所以如果你能看一眼,我会很感激。
答案 0 :(得分:3)
您所描述的是shortest path problem。有几种方法可以解决它。 Dijkstra's algorithm是最简单的实现之一,但它对您的应用程序来说太过分了。 (它找到从一个节点到所有其他节点的最短路径。)有一个名为A*的相关算法稍微复杂一点,但它确实完全符合您的要求。
答案 1 :(得分:2)
使用networkx。它很容易安装。
从游戏板的图片中我认出了苏格兰场比赛
评论你与@Bill the Lizard的对话:
您确实可以预先计算所有最短路径。节点和边缘都没有变化
您可以通过5个出租车步骤或1个地下步骤从46
到达13
。
我可能会使用一个包含所有边缘(出租车,公共汽车,地下)的“大”图表,以及几个结合出租车+公共汽车,出租车+地铁和出租车的图表(我不太记得游戏规则。 ..你必须找出有意义的东西。)
我不确定networkx中的算法如何处理关系!
因此,预先计算所有最短的路径 然后只需在需要时查看它们。
import networkx as nx
# simplified example
# data is in the format as you specified
data = data = {1: [2,3,4],
2: [1,3,5],
3: [1,2,4],
4: [1,3,5],
5: [2,4]}
# initialize empty graph
G = nx.graph()
# now we're adding all edges
# don't bother about duplicates -- they're ignored
for n1, n in data.items():
for n2 in n:
G.add_edge(n1, n2)
# get ALL shortest paths
p = nx.shortest_path(G)
# lookup when needed, e.g. from 1 to 5
p[1][5]
# gives [1, 2, 5]