Maze迷宮問題(最優解)

迷宮地形我們可以通過讀文件的形式,通過已知入口逐個遍歷座標尋找通路。

文件如圖:

wKiom1cSCnTB8pO4AAAZiAM5LuE146.png

每個座標的位置用結構體來記錄:

struct Pos    //位置座標
{
   int  _row;
   int _col;
};

定義行列範圍

#define M 10   //行
#define N 10   //列

初始化迷宮數組
將通過讀文件的方式獲取的字符轉成整型數據,保存在M行N列的數組中。

void InitMaze(int* maze)
{	
	struct WavHeadhWAV;
	FILE* fout = fopen("MazeMap.txt", "r");   // .txt文件要放在當前目錄下
	if (fout == NULL)                       // 這裏一定要檢查讀文件是否成功
	{
		cout << "can't find MazeMap.txt !" << endl<<endl;
		return;
	}
	for (int i = 0; i < M; i++)
	{
		for (int j = 0; j < N;)
		{
			char ch = fgetc(fout);
			if (ch=='1'||ch=='0')
			{
				maze[i*N + j] = ch - '0';
				j++;
			}
		}
	}
	fclose(fout);
}

回溯查找通路

利用棧來存儲通路,通過上下左右四個方向依次遍歷,如果該位置滿足條件,就將它入棧,並將該位置的數據置爲2;如果四個方向都不滿足條件就執行出棧操作,回溯查找滿足條件的位置(這時候如果棧爲空了,說明查找通路失敗),繼續循環遍歷,直到找到出口爲止。

這裏建立一個最小棧,如果找到出路,就將該棧賦給最小棧,並將出口置爲1,繼續回溯查找通路,如果又一次找到通路,就將該棧的長度與最小棧進行比較,如果該棧長度比最小棧還要小,就將它再一次賦給最小棧(保證最小棧是最短的通路),繼續回溯,直到整個棧爲空,回到了入口,程序結束。

bool SearchMazePath(int *maze, Pos entry, stack<Pos>& paths)   // 利用棧回溯查找通路,並實現迷宮的最優解
{
	assert(maze);
	stack<Pos>min;
	paths.push(entry);
	while (!paths.empty())
	{
		Pos cur = paths.top();
		maze[cur._row*N+cur._col] = 2;
		if (cur._row==M-1)
		{
			if (paths.size()< min.size() || min.size() == 0)
			{
				min = paths;
			}
			paths.pop();
			maze[min.top()._row*N + min.top()._col] = 1;
		}	
		Pos next = cur;
		next._col--;  //左
		if (CheckIsAccess(maze, next))
		{
			paths.push(next);
			maze[next._row*N + next._col] = 2;
			continue;
		}
		next = cur;
		next._col++; //右
		if (CheckIsAccess(maze, next))
		{
			paths.push(next);
			maze[next._row*N + next._col] = 2;
			continue;
		}
		next = cur;
		next._row--; //上
		if (CheckIsAccess(maze, next))
		{
			paths.push(next);
			maze[next._row*N + next._col] = 2;
			continue;
		}
		next = cur;
		next._row++; //下
		if (CheckIsAccess(maze, next))
		{
			paths.push(next);
			maze[next._row*N + next._col] = 2;
			continue;
		}
		paths.pop();
	}
	if (paths.empty()&&!min.empty())
	{
			maze[min.top()._row*N + min.top()._col] = 2;
			return true;
	}
	return false;
}

檢查該位置是否合法:(座標在行列範圍之內)

bool CheckIsAccess(int* maze, const Pos& next)    // 檢查該位置是否合法
{
	assert(maze);
	if ((next._row >= 0 && next._row <= N) && (next._col >= 0 && next._col < M) && maze[next._row*N + next._col] == 0)
	{
		return true;
	}
	return false;
}

打印迷宮:

void PrintMaze(int *maze)   // 打印迷宮
{
	assert(maze);
	for (int i = 0; i < M; i++)
	{ 
		for (int j = 0; j < N; j++)
		{
			cout << maze[i*N + j] <<" " ;
		}
		cout << endl;
	}
	cout << endl;  
}

wKioL1cSXnWRU9roAAAG8lMrhuE483.png

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