2016-06-29 43 views
2


我試圖從距原點給定距離的圖中找到路徑的所有組合。事實上,魔獸世界(軍團)的新擴張將向遊戲引入神器系統。
這是一個你可以升級的功能,每個級別給你1個等級,你可以在樹上的每個等級上花費1點。
你可以找到WOWHEAD每個工件的計算器和我會用這個作爲例子:http://legion.wowhead.com/artifact-calc/rogue/subtlety/查找距離原點給定距離的圖形中路徑的所有組合

基本上,該計劃的目標是:
「我給一個等級,比方說7,它返回給我的圖表中的每條路徑組合,我必須花費7點才能到達那裏(即,7個唯一節點的列表)「。

當我看到計算器,我認爲這是通過將其調換到一個圖形可解,所以我做了一個幫我打通: Graph

在圖中,我不得不做出一點調整從計算器,例如每個得到3個等級的特徵必須表示爲彼此相連的3個節點。另外,對於解鎖2種方式的特徵,我不得不將它們表示爲4個節點,以「模擬」3個節點的要求來通過。 (但我們會看到後,仍然是一個問題,它並沒有真正解決問題)

然後從那裏我試圖找到一個很好的方式列出每一種可能性,所以我做了大量的研究互聯網尋找處理我的問題的最佳方式。
我首先嚐試使用廣度優先搜索來解決這個問題,但是距離每個節點的起點並沒有多大幫助。 然後我試圖使用窮舉搜索。
我目前使用的代碼的適應貼有「尋找從給定圖的所有路徑」上的代碼審查@ 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,...分支添加爲鄰居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] 
} 

然後,我能得到我想要的一切對圖形的這一部分。 現在我試圖將我的推理擴展到整個圖表。但由於主要的兩個問題,我正在努力工作:
- 當我朝着一個方向前進時,用4個節點來表示具有3個等級的特徵,但是如果我填滿了整個分支,然後嘗試去回來,我計算第四個節點。 (我仍然可以在artifact函數中刪除第4個節點,但我認爲這不是一個好方法來處理它,並且應該找到一個聰明的方法來處理它。
- 我用來鏈接前兩個分支並不直接適用於整個圖表,例如,按照我所做的,我會向29個鄰居添加32,因爲當我來自35時,32可以從29開始訪問。但是,如果我來自28和沒有添加27到路徑,那麼32通常不能從29到達。 然後我的路徑變得無效。

我不確定如果我可以這樣解決它,我希望你能夠幫助我也有這樣的感覺,我的回溯搜索方式並不完美。我也認爲:
當我在一個分支結束時,我會回到之前的分離狀態並從那裏探索。但是,由於節點已經被探索,它不會走向另一個方向並停留在那裏。

最後,我可以用任何其他方式來處理我的問題,我不想特別使用圖來解決它。
也許還有另一種方法可以有效地解決它(比如一步一步地構建圖形,並且有多個隊伍可以花費並逐漸消耗它們,而節點則可以解鎖)。

預先感謝您的幫助和抱歉,我的英語水平的錯誤,我是法國人:)

+1

是不是固定最大步驟的BFS解決您的問題? – shole

回答

-1

如果您打算採取只有一個路徑,那麼你可以嘗試Dijkstra's Algorithm讓你從最初的距離節點到所有其他節點。然後只需遍歷它們就可以返回那些距離你想要的距離。

如果你想嘗試分支路徑,這可能會變得更加困難。我的本能是在其他節點上運行Dijkstra's並使用一些動態編程,但我敢打賭有一種更簡單的方法;我的計算機科學解決問題的能力並不高。

0

IIUC,你有一個加權的有向圖G,你要尋找的集合G的所有子圖即H有以下2個屬性的:

  1. 有一個路徑從給定的起源頂點到H中的每個頂點(這意味着H本身至少弱連接)
  2. 邊的總數(或權重)恰好是某個給定的k。

有這個一個簡單的算法,在那裏你保持設定爲總長度的所有子圖完全是我,並在每次迭代他們成長到集合中的所有子圖具有總長度正好我+ 1:

  1. 從集S中的單個子圖開始,只包含原點頂點。
  2. 對於i從0到K:
    • 不變:S包含一個是弱連接到原點和具有總長度精確地I G的所有子圖。
    • Set S'= {}。
    • 對於S中的每個子圖H:
      • 對於每一個邊(u,v)的其中u爲V(H)和v V(H)的外:
        • 表格子圖H」由的H,再加上邊(u,v)。
        • 將H'添加到集合S'。 (如果這張圖H'已經在S'中,則什麼也不做,這會經常發生,這就是爲什麼最好使用適合於的數據結構對於S'來說是自動處理的,例如散列表或二進制搜索樹。)
    • 設置S = S'。

當算法終止,S將包含所有子圖滿足要求1和2的上方。在最糟糕的情況下,它將需要輸出中不同子圖的數量的m倍,其中m是圖中邊的數量。請注意,輸出中可能有大量的子圖 - 考慮n個頂點上的完整圖,並注意,有多個可能的子圖比有n個k個子項的組合更多,而後者已經很大。

相關問題