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

棧求解迷宮問題

問題:假設下圖1是某迷宮的地圖(0代表路徑,1代表牆壁),問此迷宮是否有條通路?

求解思想:

用棧來實現解決問題,主要步驟是

(1)將迷宮的入口座標設為當前座標

(2)將當前座標壓棧,將當前座標上的值設為2(0變為2),代表已走過的路

(3)判斷當前座標的四周(上下左右)是否是可以通(為0則通)的,如果是通的,那就將它的座標設為當前座標

(4)重複(2)(3)的操作

(5)若遇到如圖1中標註的座標,四周都不可以通(四周都不為0),那麼就回退(將棧中的座標彈出),將棧頂座標設為當前座標,重複步驟(3)

(6)當退回到兩路的相交處則當前周圍有路可以通,重複步驟(2)(3)

(7)只要判斷當前位置在迷宮地圖的邊緣(只有邊界值為0時,當前位置才可以到達邊界),那麼就可以判斷該迷宮是否可以通

棧中的元素是迷宮通路的路線,若棧為空,則迷宮沒有通路

解題程式:

//Maze.h
#include<iostream>
#include<stack>
#include<assert.h>
using namespace std;

struct Pos
{
	int _row; //行
	int _col;//列
};
//Maze.cpp
#include "Maze.h"

bool CheckPath(int *a, Pos next, int n)
{
	if (next._col < n && next._col >= 0
		&& next._row >= 0 && next._row < n
		&& (a[next._row*n + next._col] == 0))//若行列都合法且該位置元素為0則為真
		return true;
	return false;
}
void GetMaze(int *a, int n)
{
	FILE* fout = fopen("MazeMap.txt", "r");//迷宮地圖在放在當前目錄下“MazeMap.txt”裡
	assert(fout);

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n;)
		{
			char ch = fgetc(fout);//讀檔案
			if ((ch == '0') || (ch == '1'))//若為0或1則放入陣列
			{
				a[i*n + j] = ch - '0';
				j++;
			}
			else
			{
				continue;
			}
		}
	}
	fclose(fout);//關閉檔案
}
void PrintMaze(int *a, int n)//列印迷宮
{
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout << a[i*n + j] << " ";
		}
		cout << endl;
	}
	cout << endl;

}
bool MazePath(int *a, int n, Pos entry, stack<Pos>& path)//判斷迷宮是否有通路
{
	Pos cur = entry;//將出口當做當前位置
	Pos next;
	path.push(cur);
	while (!path.empty())//若棧不為空
	{
		if (cur._col!=entry._col && cur._row!=entry._row
			&&( cur._col==n-1 || cur._col==0 || cur._row ==n-1 || cur._row ==0))//若該位置的行是最後一行,代表已走到出口位置
		{
			return true;
		}
		a[cur._row*n + cur._col] = 2;//將該位置置為2,代表已走過的路

		next = cur;
		next._col++;//若下一個位置是當前位置的右邊
		if (CheckPath(a, next, n))//若下一個位置的值合法且為0(可以通),則跳到下一個位置,且壓棧
			//若不可以通那麼就判斷令一個方向的位置的值
		{
			cur = next;
			path.push(cur);
			continue;
		}

		next = cur;
		next._row++;
		if (CheckPath(a, next, n))//同理
		{
			cur = next;
			path.push(cur);
			continue;
		}
		next = cur;
		next._row--;
		if (CheckPath(a, next, n))//同理
		{
			cur = next;
			path.push(cur);

			continue;

		}
		next = cur;
		next._col--;
		if (CheckPath(a, next, n))//同理
		{
			cur = next;
			path.push(cur);

			continue;
		}
		cur = path.top();//當四周都不可以通則回退,將當前位置置為棧頂元素的座標位置
                path.pop();//頂元素彈出
	}
	return false;//若棧為空,那麼迷宮沒有通路
}
//test.cpp
#include "Maze.h"
int const n = 10;

void TestMaze()
{
	int a[n][n] = {};
	GetMaze((int *)a, n);
	PrintMaze((int *)a, n);
	stack<Pos> path;
	Pos entry = { 2, 0 };
    bool ret = MazePath((int *)a, n, entry, path);
	cout << "是否有通路" << ret << endl;
	PrintMaze((int *)a, n);

}
int main()
{
	TestMaze();
	getchar();
	return 0;
}

執行結果:

當迷宮有出口,則執行結果如圖:返回1

當迷宮沒有出口時,執行結果如下圖:返回1