[英]Finding all combinations of paths from a graph with a given distance from the origin
我正在嘗試從距原點給定距離的圖中查找路徑的所有組合。
實際上,《魔獸世界》(軍團)的新擴展將在游戲中引入神器系統。
您可以升級此功能,每個級別給您1個等級,您可以在樹中為每個等級花費1點。
您可以在WowHead上找到每個工件的計算器,我將以它為例: http : //legion.wowhead.com/artifact-calc/rogue/subtlety/
基本上,該計划的目標是:
“我給一個等級,比方說7,它返回給我圖表中的所有路徑組合,我必須花7點才能到達那里(即7個唯一節點的列表)”。
當我看到計算器,我認為這是通過將其調換到一個圖形可解,所以我做了一個幫我打通: 圖
在圖上,我必須對計算器進行少量調整,例如,獲得3個等級的每個特征都必須表示為3個相互鏈接的節點。 另外,對於可以繼續2種方式解鎖的特征,我必須將它們表示為4個節點以“模擬” 3個節點的要求才能通過。 (但我們會在那之后看到仍然是一個問題,它並沒有真正解決問題)
然后從那里嘗試尋找一種列出所有可能性的好方法,因此我在互聯網上進行了大量研究,以找到解決問題的最佳方法。
我首先嘗試使用廣度優先搜索來解決它,但是與每個節點的原點之間的距離並沒有太大幫助。 然后,我嘗試使用窮舉搜索。
我目前正在使用這里發布的代碼的改編:CodeReview @ StackEchange上的“查找給定圖的所有路徑”(不能發布兩個以上的鏈接)
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的所有過程之后,如果我說要花10點,就不要回到2-3-...。
我可以通過在38,37,...分支中添加鄰居2或在2,3,...分支中添加38作為鄰居來解決此子圖。
所以我的清單變成了:
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個節點。 (我仍然可以在構件函數中進行某些操作以刪除第4個節點,但是我認為這不是處理它的好方法,因此應該找到一種巧妙的方法來處理它。
-我用來鏈接前兩個分支的技巧不適用於整個圖。 例如,按照我所做的,我將32添加到29s鄰居中,因為當我來自35時,可從29訪問32。但是,如果我來自28而未將27添加到路徑中,則32不是通常從29開始即可到達。然后我的路徑無效。
我不確定是否可以這樣解決,希望您能為我提供幫助。 另外,我覺得我回溯搜索的方式並不完美。 我也這樣認為:
當我到達分支的盡頭時,我將回到先前的分離並從那里開始探索。 但是,由於已經對節點進行了探索,所以別無所求。
最后,我有其他方法來解決我的問題,我不想特別使用圖形來解決它。
也許還有另一種有效解決問題的方法(例如逐步構建圖形,並在解鎖節點時讓許多等級花費並逐漸花費它們)。
預先感謝您的幫助,對於我的英語錯誤,我深感抱歉,我是法語:)
IIUC,您有一個未加權的有向圖G,並且您正在尋找G的所有子圖H的集合,這些集合具有以下2個屬性:
有一個簡單的算法,您可以維護總長度恰好為i的所有子圖的集合,並在每次迭代時將它們增長到總長度恰好為i + 1的所有子圖的集合:
當算法終止時,S將包含滿足上述要求1和2的所有子圖。 在最壞的情況下,它將花費輸出中不同子圖的數量的m倍,其中m是圖中的邊數。 請注意,有可能是大量輸出子圖-考慮n個頂點的完全圖,並注意有更多的可能子圖比也有從n個k個項目的組合,而后者已經是很大的。
如果您只想走一條路,那么可以嘗試Dijkstra的算法來獲取從初始節點到所有其他節點的距離。 然后只需遍歷它們即可返回具有所需距離的對象。
如果您想嘗試分支路徑,這可能會變得更加困難。 我的本能是在其他節點上運行Dijkstra,並使用一些動態編程,但是我敢打賭,這是一種更簡單的方法。 我的計算機科學問題解決能力很普通。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.