迷宮問題DFS

        二維整數矩陣a[N][N]表示一個迷宮,矩陣左上角表示迷宮入口,右下角表示出口。矩陣的元素爲0表示可以通過,爲1表示不能夠通過。如

maze[5][5]=
{0, 1, 1, 1, 1,
 0, 0, 0, 0, 0,
 0, 1, 0, 1, 0,
 0, 1, 0, 1, 0,
 0, 0, 0, 0, 0};

則迷宮的一條通往出口的路徑爲(0, 0)->(1, 0)->(2, 0)->(3, 0)->(4, 0)->(4, 1)->(4, 2)->(4, 3)->(4, 4)。

設計一個算法,求通往迷宮出口的所有路徑。

       可以考慮使用DFS算法,將已經訪問過的矩陣元素做一個標記,以防止路徑產生迴路,從而產生死循環。但是,簡單的對元素進行訪問標記會遺漏一些路徑。

這是因爲,通往迷宮出口的不同路徑有可能有交點。當所有路徑的交點多於兩個時,由於先獲取的路徑會將交點元素標記爲已經訪問。當存在其他通過該節點的路徑

時,由於該交點已經被標記爲已訪問,所以其他的通過該交點的路徑將被忽略。

      解決這個問題只需要對算法稍加改動即可。思路爲:當某一個節點DFS完成後,擦除該節點的訪問痕跡。

代碼如下:

#include<iostream>
#include<deque>
using namespace std;

class Point
{

public:
	int i;
	int j;
	Point(int x, int y)
	{
		i=x;
		j=y;
	}
};// 節點座標結構體

deque<Point> q;// 用一個隊列記錄路徑
int N=5;// 迷宮的大小
int maze[5][5]=
{0, 1, 1, 1, 1,
 0, 0, 0, 0, 0,
 0, 1, 0, 1, 0,
 0, 1, 0, 1, 0,
 0, 0, 0, 0, 0};// 迷宮矩陣
int path[5][5]=
{0, 0, 0, 0, 0,
 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0};// 訪問標記矩陣

void dfs(int i, int j);

void main()
{
	path[0][0]=1;
	q.push_back(Point(0, 0));
	dfs(0, 0);
	q.pop_back();
	//system("pause");
}

void dfs(int i, int j)
{
	if(N-1==i && N-1==j)
	{
		path[i][j]=0;
		cout<<"Path:"<<endl;
		for(deque<Point>::iterator it=q.begin(); it!=q.end(); it++)
		{
			cout<<(*it).i<<", "<<(*it).j<<endl;
		}
		return;
	}
	if(i>0 && 1!=maze[i-1][j] && 1!=path[i-1][j])
	{
		path[i-1][j]=1;// 標記節點已經被訪問過,避免路徑產生迴路,從而產生死循環
		q.push_back(Point(i-1, j));
		dfs(i-1, j);
		q.pop_back();
		//path[i-1][j]=0;
	}
	if(i<N-1 && 1!=maze[i+1][j] && 1!=path[i+1][j])
	{
		path[i+1][j]=1;
		q.push_back(Point(i+1, j));
		dfs(i+1, j);
		q.pop_back();
		//path[i+1][j]=0;
	}
	if(j>0 && 1!=maze[i][j-1] && 1!=path[i][j-1])
	{
		path[i][j-1]=1;
		q.push_back(Point(i, j-1));
		dfs(i, j-1);
		q.pop_back();
		//path[i][j-1]=0;
	}
	if(j<N-1 && 1!=maze[i][j+1] && 1!=path[i][j+1])
	{
		path[i][j+1]=1;
		q.push_back(Point(i, j+1));
		dfs(i, j+1);
		q.pop_back();
		//path[i][j+1]=0;
	}
	path[i][j]=0;// 擦除訪問痕跡
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章