我试图从距离原点给定距离的图表中找到所有路径组合。
事实上,魔兽世界(军团)的新扩展将把神器系统引入游戏中
它是一个可以升级的功能,每个级别为您提供1个等级,您可以为树中的每个等级花费1个点。
您可以在WowHead上找到每个工件的计算器,我将以此为例:http://legion.wowhead.com/artifact-calc/rogue/subtlety/
基本上,该计划的目标是:
"我给出一个等级,让我们说7,然后它返回给我来自图表的每个路径组合,我不得不花7点到达那里(即7个独特节点的列表)&#34 ;
当我看到计算器时,我认为它可以通过将其转换为图表来解决,所以我做了一个来帮助我完成: Graph
在图表上,我不得不对计算器进行一些调整,例如,获得3个等级的每个特征必须表示为3个相互连接的节点。 此外,对于解锁2种继续方式的特征,我不得不将它们表示为4个节点来模拟"模拟"要通过的3个节点要求。 (但我们会在那之后看到仍然是一个问题而且它并没有真正解决问题)
然后从那里我试图找到列出所有可能性的好方法,所以我通过互联网进行了大量研究,以找到解决问题的最佳方法。
我首先尝试使用广度优先搜索来解决它,但距离每个节点的原点的距离并没有多大帮助。
然后我尝试使用详尽的搜索
我目前正在使用在那里发布的代码的修改:"查找来自给定图表的所有路径"在CodeReview @ StackEchange上(不能发布2个以上的链接)
def paths(graph, v, lmax):
"""Generate the maximal cycle-free paths with a given maximum length lmax in
graph starting at v. Graph must be a mapping from vertices to collections of
neighbouring vertices.
>>> g = {1: [2, 3], 2: [3, 4], 3: [1], 4: []}
>>> sorted(paths(g, 1, 3))
[[1, 2, 3], [1, 2, 4], [1, 3]]
>>> sorted(paths(g, 3, 4))
[[3, 1, 2, 4]]
Credit to Gareth Rees from StackExchange for the original code.
"""
path = [v] # path traversed so far
seen = {v} # set of vertices in path
def search():
dead_end = True
if len(seen) < lmax:
for neighbour in graph[path[-1]]:
if neighbour not in seen:
dead_end = False
seen.add(neighbour)
path.append(neighbour)
yield from search()
path.pop()
seen.remove(neighbour)
if dead_end:
yield list(path)
yield from search()
然后我创建一个函数来对结果进行排序,并只显示具有所需长度的结果。
def artifact(graph, maxrank, start):
for i in range(1, maxrank+1):
print("---------")
print("Rank: " + str(i))
print("---------")
# Get all the Paths at "i" Rank
RawPaths = sorted(paths(g, start, i), key=len)
# Remove paths that doesn't satisfact our rank requirement and sort it
ValidPaths = [sorted(j) for j in RawPaths if len(j) == i]
# Remove duplicates
UniquePaths = sorted([list(j) for j in set(map(tuple, ValidPaths))])
# Display the Paths
for j in range(len(UniquePaths)):
PathString = "";
for k in range(len(UniquePaths[j])):
PathString += str(UniquePaths[j][k]) + " "
print(PathString)
print("")
从那里,我从图中构建了一部分节点的相邻节点(邻居)列表。我不能发布超过2个链接,但子图结束于之前链接的图形的8/7/32/31个节点。
g = {
1: [2, 38],
2: [1, 3],
3: [2, 4],
4: [3, 5],
5: [4, 6],
6: [5, 7, 8],
7: [6],
8: [6],
31: [33],
32: [33],
33: [31, 32, 34],
34: [33, 35],
35: [34, 36],
36: [35, 37],
37: [36, 38],
38: [1, 37]
}
然后我调用了我的功能:
artifact(g, 8, 1)
但是使用这个列表,我遇到了一个重大问题。实际上,算法一直持续到结束,但它没有做任何回溯以达到所需的等级(即,在经过1 - 38 - 37 - 36 - 35 - 34 - 33 - 31之后,它不会回到2 - 3 - 如果我让他们说要花10分。)
通过将38,37,...分支或38添加为邻居2,我能够为此子图解决它。
所以我的名单变成了:
g = {
1: [2, 38],
2: [1, 3, 38],
3: [2, 4, 38],
4: [3, 5, 38],
5: [4, 6, 38],
6: [5, 7, 8, 38],
7: [6, 38],
8: [6, 38],
31: [2, 33],
32: [2, 33],
33: [2, 31, 32, 34],
34: [2, 33, 35],
35: [2, 34, 36],
36: [2, 35, 37],
37: [2, 36, 38],
38: [1, 2, 37]
}
然后我能够获得我想要的图的这一部分。
现在我试图将我的推理扩展到整个图表。但由于主要的两个问题,我没有成功:
- 当我向一个方向前进时,表示具有3个等级的特征的4个节点正在工作,但是如果我已经填满整个分支然后我尝试返回,则计算第4个节点。 (我仍然可以在神器功能中创建一些东西来移除第四个节点,但我认为这不是一个处理它的好方法,应该找到一个聪明的方法来处理它。
- 我用来链接前两个分支的技巧不能直接应用于整个图形。例如,按照我所做的,我会向29s邻居添加32,因为当我来自35时,32可从29访问。但是,如果我来自28并且没有添加27到路径,那么32通常不能从29开始到达。
然后我的路径变得无效。
我不确定我是否可以这样解决,希望你能帮助我。此外,我感觉我的回溯搜索方式并不完美。
我也这么想:
一旦我在分支结束时,我会回到之前的分离并从那里开始探索。但是,由于该节点已经被探索过,所以它不会走另一条路并停在那里。
最后,我可以通过任何其他方式来处理我的问题,我不想特别想用图表来解决它。
也许还有另一种方法可以有效地解决它(比如逐步构建图形并有多个等级可以花费并逐渐花费它们,而节点可能会被解锁?)。
提前感谢您的帮助,对不起我的英语错误,我是法语:)
答案 0 :(得分:0)
IIUC,你有一个未加权的有向图G,你正在寻找具有以下2个属性的G的所有子图H的集合:
这是一个简单的算法,你可以维护所有子图的集合,其总长度恰好为i,并且在每次迭代时将它们增长到所有子图的集合,其总长度恰好为i + 1:
当算法终止时,S将包含符合上述要求1和2的所有子图。在最坏的情况下,它将花费m倍于输出中不同子图的数量,其中m是图中边的数量。请注意,输出中可能存在大量子图 - 考虑n个顶点上的完整图形,并注意有多个更多可能的子图,而不是来自n的k个项的组合,并且后者已经很大了。
答案 1 :(得分:-1)
如果您打算只采用一条路径,那么您可以尝试使用Dijkstra's Algorithm来获取从初始节点到所有其他节点的距离。然后迭代它们以返回具有所需距离的那些。
如果您想尝试分支路径,这可能会变得更加困难。我的直觉是在其他节点上运行Dijkstra并使用一些动态编程,但我敢打赌,这是一种更简单的方法;我的解决计算机科学问题的能力不高。