寬度優先搜索(BFS)也是搜索的手段之一。它與深度優先搜索相似,從某個狀態出發搜索全部可達的狀態。前端
與DFS不一樣的是搜索的順序,寬度優先搜索老是先搜索離初始狀態近的狀態。也就是說,它是按照開始狀態--->只需1次轉移就能夠到達的全部狀態--->只需2次轉移就能夠到達的全部狀態--->......,以這樣的順序開始搜索,對於同一個狀態,寬度優先搜索只通過一次,所以時間複雜度:O(狀態數 * 轉移的方式)。ios
深度優先搜索隱式利用了棧進行計算(遞歸的基礎即是棧),而寬度優先搜索則利用了隊列。搜索時首先將初始狀態添加到隊列裏,此後從隊列的最前端不斷取出狀態,把從該狀態能夠轉移到的狀態中還沒有訪問過的部分加入隊列,如此往復知道隊列爲空或找到問題的解。數組
隊列的特性爲先進先出,那麼咱們就能夠知道全部的狀態都是按照初始狀態由近及遠的順序被遍歷的。spa
迷宮問題:code
給定一個大小爲N×M的迷宮。迷宮由通道和牆壁組成,每一步能夠向鄰接的上下左右四格
的通道移動。請求出從起點到終點所需的最小步數。請注意,本題假定從起點必定能夠移動
到終點。blog
輸入
N=10, M=10(迷宮以下圖所示。'#','.','S','G'分別表示牆壁、通道、起點和終點)
#S######.#
......#..#
.#.##.##.#
.#........
##.##.####
....#....#
.#######.#
....#.....
.####.###.
....#...G#遞歸
輸出
22隊列
分析:起點狀態其實就對應初始狀態,起點可走周圍四個方向(過程當中需對是否越界,是否撞牆作出判斷,不知足條件都爲不可到達的狀態),一旦遍歷的點爲終點這時經歷的路徑必爲最短,由於寬度優先搜索是由近到遠的,因此第一個來到終點的路徑必爲最短。過程當中用二維數組d將到達每一個點的最短路徑保存下來。ci
因爲要向四個方向移動,用dx和dy兩個數組來表示四個方向向量。string
#include<iostream> #include<cstring> #include<queue> using namespace std; #define INF 0x3f3f3f3f typedef pair<int,int> P; const int MAX = 100; char maze[MAX][MAX+1]; int m,n; int sx,sy;//起點座標 int gx,gy;//終點座標 int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1}; int d[MAX][MAX+1]; int bfs(){ queue<P> que; //尋找起點和終點座標 for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(maze[i][j]=='S'){ sx=i;sy=j; } if(maze[i][j]=='G'){ gx=i;gy=j; } } } memset(d,INF,sizeof(d)); //將初始狀態(起點)加入隊列 que.push(P(sx,sy)); d[sx][sy]=0; while(que.size()){ //取出隊頭 P p = que.front(); que.pop(); int nx=p.first,ny=p.second; if(nx==gx&&ny==gy){ break; } for(int i=0;i<4;i++){ //移動後的位置記爲(nx,ny) nx=p.first + dx[i];ny=p.second + dy[i]; if(nx>=0&&ny>=0&&nx<m&&ny<n&&d[nx][ny]==INF&&maze[nx][ny]!='#'){ d[nx][ny]=d[p.first][p.second]+1; que.push(P(nx,ny)); } } } return d[gx][gy]; } int main(){ cin>>m>>n; for(int i=0;i<m;i++){ cin>>maze[i]; } cout<<bfs()<<endl; // cout<<sx<<" "<<sy<<endl; // cout<<gx<<" "<<gy<<endl; return 0; }