深度優先搜索算法(英語:Depth-First-Search,簡稱DFS)是一種用於遍歷或搜索樹或圖的算法。沿着樹的深度遍歷樹的節點,盡可能深的搜索樹的分支。當節點v的所在邊都己被探尋過,搜索將回溯到發現節點v的那條邊的起始節點。這一過程一直進行到已發現從源節點可達的所有節點為止。如果還存在未被發現的節點,則選擇其中一個作為源節點並重復以上過程,整個進程反復進行直到所有節點都被訪問為止。屬於盲目搜索。
深度優先搜索是圖論中的經典算法,利用深度優先搜索算法可以產生目標圖的相應拓撲排序表,利用拓撲排序表可以方便的解決很多相關的圖論問題,如最大路徑問題等等。(摘自wiki百科)

(圖片來自網絡)
算法實現:利用函數棧來保存當前搜索路徑中每個節點的狀態,每搜索一個新節點,就標記此節點被使用並遞歸調用一次dfs函數,確定此節點在本路徑中無法到達終點,則return上一級函數,更換下一節點。
注意問題:1、回溯后是否要將節點標記重置應該看路徑來源是否會對節點能否到達出口產生影響,如果任意路徑到達此節點都不會影響它能否到達終點,則不去除標記,因為即使下一次搜索到它,也知道它無法到達終點,從而跳過它。
如果不同路徑來源會影響,則需要重置標記,保證能被其他路徑再次選取。
2、剪枝,通過對題目的理解,在選取節點遞歸之前,直接判斷此節點能否到達終點,從而減少大量不必要的搜索過程。
可以參考博文:http://blog.csdn.net/u010700335/article/details/44079069
更多技巧需要在寫題目中自己探索~
帶注釋模板:
HDU-1181
1 //DFS模板題 HDU 1181 2 3 #include <iostream> 4 #include <string.h> 5 #include <queue> 6 #include <string> 7 using namespace std; 8 string str[300]; 9 int vis[300],i;//標記數組,在一條路徑中,被查找過的節點不能被再次查找,不然就會使路徑出現循環 10 int flag = 0;//用於判定搜索是否查找到路徑 11 void dfs(string use) 12 { 13 char last = use[use.length() - 1]; 14 if (flag == 1)//如果已經找到了就直接結束,減少不必要的搜索過程 15 return; 16 for (int k = 0;k<i;k++)//如果視當前use字符串為當前節點,那么for循環就應該遍歷下一層的所有可能節點 17 { 18 if (vis[k] == 0&& str[k][0] == last)//如果未被訪問,且其首字符合本節點末字符匹配,就可以作為搜索樹的分支節點 19 { 20 vis[k] = 1;//每確定路徑中的一個節點,就標記起來 21 if (str[k][str[k].length() - 1] == 'm')//滿足搜索的結束條件就設置flag並退出 22 { 23 flag = 1; 24 return; 25 } 26 else 27 dfs(str[k]);//否則繼續向下搜索 28 //vis[k]=0 29 //大部分DFS在一條路徑搜索失敗后都需要回溯到上一狀態 30 //通常需要把從本節點后產生的標記都重置 31 //實際上是否需要重置標記,應該看路徑來源是否會對節點能否到達出口產生影響 32 //在本題中。如果str[k]是到所求路徑中的一個節點,不管從什么途徑搜索到了str[k],都不影響他到達終點。 33 } 34 } 35 } 36 int main() { 37 38 while (cin >> str[i]) 39 { 40 if (str[i] == "0") 41 { 42 memset(vis, 0, sizeof(vis)); 43 flag = 0; 44 for (int j = 0;j<i;j++) 45 { 46 if (str[j][0] == 'b')//如果滿足起始條件就進入搜索過程 47 { 48 vis[j] = 1; 49 dfs(str[j]); 50 } 51 } 52 i = 0;//有多組測試樣例,每完成一組,重置i 53 if (flag == 1) 54 cout << "Yes." << endl; 55 else 56 cout << "No." << endl; 57 } 58 else 59 i++; 60 } 61 return 0; 62 }
