DFS--求解迷宮問題
阿新 • • 發佈:2018-12-09
問題:從(0,0)出發到(n-1,m-1)的路徑
輸入:
6 80 0 1 0 0 0 1 1
1 0 0 0 1 0 0 0
0 0 0 1 1 0 1 1
1 1 0 1 0 0 0 0
0 0 0 0 0 1 0 1
1 0 1 0 0 0 0 0 輸出:
(0,0)
(0,1)
(1,1)
(1,2)
(1,3)
(0,3)
(0,4)
(0,5)
(1,5)
(2,5)
(3,5)
(3,6)
(4,6)
(5,6)
(5,7)
解題思路:就是dfs搜尋,起點是(0,0),終點是(n-1,m-1),如果到達終點就直接返回,否則遞迴dfs搜尋其上下左右四個方向的
點,這四個方向可用int move[4][2]={{0,1},{1,0},{0,-1},{-1,0}};表示,四個方向要滿足一下條件才能被訪問,1 就是未被訪問過visited[i][j]==0且是通道map[i][j]==0,才能訪問,注意因為求的是路徑,所以根據遞迴的特點先返回的是終點,所以可以用棧來存放,然後逐個pop就是正確的路徑順序了。但是dfs求的不是最短的路徑,而bfs求的是最短路徑。需要用到佇列。
總結:
①從起點開始dfs滿足條件將起點入棧
②開始遍歷該點的四周(就像圖中的訪問到該點時,就要遍歷與其相連且未被訪問的點,滿足條件再dfs
只不過visited是一維陣列作為標記是否訪問過)
③:四周滿足條件的標記好已訪問再dfs,然後返回 1;
④:就是不斷的pop。直到棧為空
#include<iostream> #include<algorithm> #include<stack> using namespace std; typedef pair<int,int> p; const int N=500; int visited[N][N],map[N][N]; int dfs(int x,int y); int move[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; int n,m; stack<p>s; int main(){ cin>>n>>m; for(int i=0;i<n;i++) for(int j=0;j<m;j++) cin>>map[i][j]; for(int i=0;i<n;i++) for(int j=0;j<m;j++) visited[i][j] = 0; if(dfs(0,0)){ s.push(make_pair(0,0)); } while(!s.empty()){ p t = s.top(); cout<<"("<<t.first<<","<<t.second<<")"<<endl; s.pop(); } return 0; } int dfs(int x,int y){ visited[x][y] = 1; if(x==n-1&&y==m-1)return 1; for(int i=0;i<4;i++){ int x1 = x+move[i][0]; int y1 = y+move[i][1]; if(x1<n&&y1<m&&x1>=0&&y1>=0&&visited[x1][y1]==0&&map[x1][y1]==0){ visited[x1][y1] = 1; if(dfs(x1,y1)){ s.push(make_pair(x1,y1)); return 1; } } } return 0; }