2013-06-02 18 views
0

我可能會丟失一些關於DFS/DLS時,維基百科不說訪問節點應該與當前深度連接起來......算法 - DFS極其緩慢保持visisted節點

問題:你有這樣的2x4地圖S =啓動E =出口

____ 
E | 
    | 
    | 
S | 

如果您正在使用DFS MAXDEPTH = 3,您的移動發電機是:

dir = {right, left, up, down} 

DFS不會在深度爲3(這意味着IDDFS將解決這一失敗太...)

DFS會嘗試這條道路首先:如果你是標誌着拜訪位置現在E爲僅在深度可達5 DFS以來將回溯到深度0找到

____ 
E | 
    | 
3 2 | 
0 1 | 

的第一次移動'up'已經不再有效,因爲它已經在第3深度了!

我看到的唯一解決方案是標記與當前的深度被訪問的位置(因此可以忽略一個「訪問」的位置,如果visited.depth> currentDepth),這意味着每個位置將在每個DFS搜索被訪問很多很多次當深度= X時,不可能在大問題中使用!

在我的測試中,如果你有足夠的內存在一個大問題中運行廣度優先搜索,它將比深度= X處的DFS運行更快,即使X是最短深度來解決..它聽起來是我'錯了,但我只是沒有看到它爲什麼或什麼我doig錯了..有人請賜教! (是的,這是問題...我不知道發生了什麼事)

這是我的搜索功能,以解決難題:
BFS(偉大工程,但不是很大的問題..使用了大量的RAM)
注意到我沒有使用的hasmap的值(通常爲0)

HashMap<State, Integer> table = new HashMap(); 

State bfs() { 
    State state = this.initState; 
    Queue<State> pending = new LinkedList(); 
    table.put(state, 0); 
    pending.add(state); 
    while (!pending.isEmpty()) { 
     state = pending.remove(); 
     for (State child : state.getChildren()) { 
      if (!table.containsKey(child)) { 
       table.put(child, 0); 
       if (child.isSolved()) 
        return child; 
       pending.add(child); 
      } 
     } 
    } 
    return null; 
} 

DFS(很慢,過多的節點,不能用於大問題)
注意hashMap.put還更新舊值

State dls(State state, int depth) { 
    if (depth == maxDepth) 
     return state.isSolved() ? state : null; 
    for (State child : state.getChildren()) { 
     if (!table.containsKey(child) || 
       table.get(child) > depth) { 
      table.put(child, depth); 
      State solution = dls(child, depth + 1); 
      if (solution != null) 
       return solution; 
     } 
    } 
    return null; 
} 

State solution(int depth) { 
    this.maxDepth = depth; 
    table.put(this.initState, 0); 
    return dls(this.initState, 0); 
} 

回答

0

你想解決什麼問題? DFS傳統上用於解決迷宮,因爲它有一個理論,它會首先到達迷宮的末端,因爲它首先搜索深度,但我相信一般BFS將一樣快。

在這種情況下,它看起來像DFS會工作得很好,但是,您將在圖形到達那裏之前訪問許多節點。

這裏是一個可能的DFS遍歷:

____ 
7 6 | 
4 5 | 
3 2 | 
0 1 | 

你從哪裏開始在0到7都爲DFS的步驟如下:

  1. 從0開始,將其添加到一個堆棧。
    • 堆棧:{0}
  2. 刪除0,它的三個孩子(3,2,1)添加到堆棧中。將0標記爲已訪問。
    • 堆棧:{3,2,1}
  3. 取出1,它的三個孩子(0,3,2)添加到堆棧中。然而,0被訪問,所以跳過它。標記爲1已訪問。
    • 堆棧:{3,2,3,2}
  4. 刪除2,它的三個孩子(3,4,5)添加到堆棧中。標記2被訪問。
    • 堆棧:{3,2,3,2,5,4,3}

...

最終,你將在E結束了,但你的籌碼將有它中有許多節點。每次你彈出一個節點時,你都必須檢查它是否被訪問過,如果它什麼也不做。

正如你所看到的,這是一個非常緩慢的算法,因爲圖是連通的。


一個更好的辦法來找到發E是使用Shortest PathsA*

0

天真DFS已完成,但非最佳。 這意味着它保證一個解決方案,如果存在,但不能保證它是最佳的。雖然一個選擇尋找最佳的解決方案是你所採取的方法,它使得現在DFS比BFS一個更糟糕的選擇,因爲它現在需要擴大每個節點高達每一個可能的路徑,而BFS只需要擴大每個節點。

對於這種情況,你是正確的,BFS比DFS更好,因爲你有很多可能的路徑的小的搜索空間,並正在努力尋找最佳的解決方案。不同的問題,不同的算法更好。 A*Dijkstra's是將在這種情況下,比BFS進行更好的算法的例子。

When is it practical to use DFS vs BFS?有大約每種方法的相對利益的更多信息。