1. 程式人生 > >通俗理解BFS和DFS,附基本模板

通俗理解BFS和DFS,附基本模板

1.BFS(寬度優先搜尋):使用佇列來儲存未被檢測的節點,按照寬度優先的順序被訪問和進出佇列

打個比方:(1)類似於樹的按層次遍歷

     (2)你的眼鏡掉在了地上,你趴在地上,你總是先摸離你最近的地方,如果沒有,再摸遠一點的地方……

 1 BFS演算法:
 2 
 3 通常用佇列(先進先出,FIFO)實現
 4 
 5 初始化佇列Q;
 6 Q = {起點s};
 7 標記s為已訪問;
 8 while(Q非空)
 9 {
10     取Q隊首元素u;
11     u出隊;
12     if(u==目標狀態)
13     {
14         ……
15     }
16 else 17 { 18 所有與u相鄰且未被訪問的點進入佇列; 19 標記u為已訪問; 20 } 21 }

 

 1 //BFS演算法框架
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<queue>
 6 #include<algorithm>
 7 using namespace std;
 8 
 9 const int maxn = 100;
10 bool
mark[maxn][maxn]; //訪問標記 11 int go[4][2] = {0,-1,1,0,0,1,-1,0}; //方向向量 12 13 struct State 14 { 15 int x,y; //座標位置 16 int step; //搜尋步數記錄 17 }; 18 19 State maze[maxn]; 20 21 bool CheckState(State s) 22 { 23 if(!mark[s.x][s.y]&&(邊界條件滿足)) //符合條件 24 return 1; 25 else //不符合條件 26 return
0; 27 } 28 29 void BFS(State st) 30 { 31 queue<State> q; 32 State now,next; 33 st.step = 0; //步數清零; 34 q.push(st); //入隊; 35 mark[st.x][st.y] = 1; //訪問標記 36 while(!q.empty()) 37 { 38 now = q.front(); //取隊首元素進行拓展 39 q.pop(); //隊首元素出隊; 40 if(now == 目標狀態) //出現目標狀態,此時的step為最小值,做做相關處理後退出即可; 41 { 42 ……; 43 return ; 44 } 45 //如果沒有到目標狀態: 46 else 47 { 48 for(int i=0;i<4;i++) 49 { 50 next.x = now.x + go[i][0];//按照規則生成下一個狀態 51 next.y = now.y + go[i][1]; 52 if(CheckState(next)) //如果狀態滿足條件則入隊; 53 { 54 next.step = now.step + 1; 55 q.push(next); 56 } 57 } 58 } 59 return ; 60 } 61 } 62 63 int main() 64 { 65 ……; 66 BFS(); 67 ……; 68 return 0; 69 }

 

DFS (深度優先搜尋):一直往下搜,知道找到解或者走不下去為止

打個比方:(1)類似於樹的先根遍歷

     (2)類似於你在走迷宮,你不能分身來站在每個走過的位置,所以,你只能不撞南牆不回頭。

 

 1 DFS:
 2 
 3 使用棧來儲存未被檢測的節點,
 4 節點按照深度優先的次序被訪問並依次壓入棧中,並已相反的次序出棧進行新的檢測。
 5 
 6 DFS(dep,……)//dep代表目前DFS的深度
 7 {
 8     if(找到解||走不下去了)
 9     {
10         ……;
11         return12     }
13     else
14     {
15         列舉下一種情況;
16         DFS(dep+1,……);
17     }
18 }

 

 1 //DFS演算法框架:
 2 
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 using namespace std;
 7 
 8 const int maxn = 100;
 9 bool mark[maxn][maxn]; //訪問標記
10 int maze[maxn][maxn]; //座標範圍
11 int go[4][2] = {0,-1,1,0,0,1,-1,0}; //方向向量
12 
13 bool CheckState(int x,int y)
14 {
15     if(!mark[x][y]&&……) //滿足條件
16         return 1;
17     else //與約束條件衝突
18         return 0;
19 }
20 
21 void DFS(int x,int y)
22 {
23     mark[x][y] = 1; //標記該節點被訪問過
24     if(maze[x][y] == G) //出現目標狀態G
25     {
26         …… //做相應處理
27         return ;
28     }
29     else
30     {
31         for(int i=0;i<4;i++)
32             if(CheckState(x+go[i][0],y+go[i][1])) //按照規則生成下一個節點
33                 DFS(x+go[i][0],y+go[i][1]);
34     }
35     return ; //如果沒有下層搜尋點,則回溯;
36 }
37 
38 int main()
39 {
40     ……;
41     return 0;
42 }