1. 程式人生 > >DFS--求解迷宮問題

DFS--求解迷宮問題

問題:從(0,0)出發到(n-1,m-1)的路徑

輸入:

6 8
0 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;
}