关于栈与递归求解迷宫与迷宫最短路径问题

一、栈实现迷宫问题:

问题描述:用一个二维数组模拟迷宫,其中1为墙,0为通路,用栈方法判断迷宫是否有出口,下图为简单模拟的迷宫:

关于栈与递归求解迷宫与迷宫最短路径问题_第1张图片

思想:

1.首先给出入口点,如上图入口点坐标为{2,0};

2.从入口点出发,在其上下左右四个方向试探,若为通路(值为0)时,则向前走,并将每次通路结点入栈(push)保存和标记走过的路为2;

3.当四个方向都没有通路时,则开始回溯,将栈中保存的结点开始pop,并将每个pop位置标记为3,直到在一个位置重新找到新的路,若没有新路,栈最终将为空,即迷宫没有出口;

4.当栈不为空,并且如在上图例子中找到位置{9,2},即其横坐标=行数-1时,则找到迷宫出口,此时栈中保存着这条通路路径。

代码实现:

#include 
#include 
#include 
#include 
using namespace std;

const size_t N=10;
struct Pos
{
	int _row;
	int _col;
};

bool CheakIsAccess(int *maze,size_t n,Pos pos)  //判断每走一次是否为通路(栈)
{
	if((maze[pos._row*n+pos._col]==0)&&(pos._row>=0&&pos._row=0&&pos._col &path)  //栈方法判断迷宫是否有出口
{
	assert(maze);
	Pos cur=entry; //cur保存当前位置
	path.push(cur);
	Pos next=cur;  //next保存下一个位置
	while(!path.empty())
	{
		cur=path.top();
		maze[cur._row*n+cur._col]=2;  //标记走过的路
		if(cur._row==n-1)   //找到一条通路
		{
			return true;
		}
		//试探法:上下左右判断是否有通路
		//上
		next=cur;
		next._row-=1;
		if(CheakIsAccess(maze,n,next))
		{
			path.push(next);
			continue;
		}
		//右
		next=cur;
		next._col+=1;
		if(CheakIsAccess(maze,n,next))
		{
			path.push(next);
			continue;
		}
		//下
		next=cur;
		next._row+=1;
		if(CheakIsAccess(maze,n,next))
		{
			path.push(next);
			continue;
		}
		//左
		next=cur;
		next._col-=1;
		if(CheakIsAccess(maze,n,next))
		{
			path.push(next);
			continue;
		}
		maze[cur._row*n+cur._col]=3;  //若四个方向都没有通路为死路时标记为3
		path.pop();     //并且回溯
	}
	return false;
}

void GetMaze(int *maze,size_t N)   //获取迷宫
{
	FILE *fout=fopen("MazeMap.txt","r");  //在文件中读取
	assert(fout);
	for(size_t i=0;i path;
	Pos entry={2,0};   //入口
	maze[entry._row][entry._col]=2;//标记入口先为2
    //栈寻找迷宫是否有出口
	GetMazePath((int*)maze,N,entry,path);
	PrintMaze((int*)maze,N);
	cout<<"迷宫是否有通路?"<
结果显示:

关于栈与递归求解迷宫与迷宫最短路径问题_第2张图片

栈中保存路径:

关于栈与递归求解迷宫与迷宫最短路径问题_第3张图片


二、递归实现迷宫最短路径问题

问题描述:迷宫中有几条通路路径,用递归求解迷宫中的最短路径,如下迷宫图:

关于栈与递归求解迷宫与迷宫最短路径问题_第4张图片

思想:

1.找到入口点,上下左右试探,试探时若下一个位置为0或者若下一个位置值大于原位置值加1,则表示为一个通路,若找到通路则递归调用自身,每走一次标记其值为前一个值加1,并将每个位置入栈保存;

关于栈与递归求解迷宫与迷宫最短路径问题_第5张图片

2.若找到通路将此时原栈中保存的路径保存到另一个空栈ShortPath中,原栈则pop,并且递归结束返回;

关于栈与递归求解迷宫与迷宫最短路径问题_第6张图片

3.如上图返回到位置{6,7},其左边为0为通路,在开始递归调用,调用到{6,6},值变为18,其左边位置为0通路,调用到{6,5},值变为19,下一个位置值都不大于原位置值加1,在此递归结束原路返回;

4.再返回到位置{6,4},其右边位置值大于{6,4}位置值加1,为通路,在此开始递归调用,每次下一个位置值都大于原位置值加1,再此找到第二条通路;

关于栈与递归求解迷宫与迷宫最短路径问题_第7张图片

5.将此时栈与ShortPath的个数size比较,若小于,则在将此时栈内容赋于ShortPath中;

关于栈与递归求解迷宫与迷宫最短路径问题_第8张图片

6.原栈再次pop,递归又一次结束原路返回,最终到入口点,原栈为空,ShortPath保存路径为迷宫最短路径。


代码实现:

bool CheakIsAccess(int *maze,size_t n,Pos cur,Pos next)  //判断每走一次是否为通路(递归)
{
	if((maze[next._row*n+next._col]==1)||(next._row<0||next._row>=n)||(next._col<0||next._col>=n))
	{
		return false;
	}
	if(maze[next._row*n+next._col]==0)
	{
		return true;
	}
	if(maze[next._row*n+next._col]>maze[cur._row*n+cur._col]+1)//若next位置值大于cur位置值加1则表示为一个新路
	{
		return true;
	}
	return false;
}

void GetMazePathR(int *maze,size_t n,Pos entry,stack &path,stack &ShortPath)  //递归方法求解最短路径
{
	assert(maze);
	Pos cur=entry;
	path.push(cur);
	Pos next=cur;
	if(cur._row==n-1)
	{
		if(ShortPath.empty()||path.size() path;
	stack ShortPath; //(递归实现中)保存栈中最短路径
	Pos entry={2,0};   //入口
	maze[entry._row][entry._col]=2;//标记入口先为2
	//递归寻找迷宫最短路径
    GetMazePathR((int*)maze,N,entry,path,ShortPath); 
    PrintMaze((int*)maze,N);
    cout<<"迷宫是否有通路?"<

你可能感兴趣的:(数据结构,数据结构)