迷宫问题-----深度优先回溯算法C++编程练习

没有对程序进行优化,使用最原始的想法进行编程。

/*
迷宫问题的深度优先回溯法---C++编程练习
Author : Michael
Date : 2014-12-31
E-mail : 1192065414@qq.com
**/

#include <iostream>
#include <stack>
#include <string>
#include <map>
using namespace std;

/* 使用二维数组记录迷宫 */
#define MAX_ROW_SIZE 8
#define MAX_COLUMN_SIZE 11
const char cMouseMap[MAX_ROW_SIZE][MAX_COLUMN_SIZE] = {
	{1,1,1,1,1,1,1,1,1,1,1},
	{1,0,1,1,0,1,1,1,1,1,1},
	{1,0,0,0,0,1,1,1,1,1,1},
	{1,1,1,0,0,0,1,1,1,1,1},
	{1,1,0,1,1,0,1,0,1,1,1},
	{1,1,0,0,0,0,1,0,0,0,1},
	{1,1,0,0,0,0,0,0,1,0,1},
	{1,1,1,1,1,1,1,1,1,1,1}
};

/*
我们需要记录,有哪些线路我们已经搜索过的,还有哪些路是暂未搜索过的(sPath 结构体对应元素值为 0),
而且需要记录那一些探索过的路是通的,正在走的路(sPath 结构体对应元素值为 1),哪些是不通的(sPath 结构体对应元素值为 -1)
若还没有到终点,而且保存结果的栈不空,表明还没有探索完,继续找一个还没有探索过的路进行探索(sPath 结构体对应元素值为 0)
*/

typedef struct sPoint {
	sPoint():x(0),y(0) {}
	int x;
	int y;
}sPoint;

typedef struct sPath {
	sPath():left(0),up(0),right(0),down(0) {}
	int left;
	int up;
	int right;
	int down;
}sPath;

/* 记录搜索路径的每个节点
   sPoint : 迷宫中的位置的点坐标
   sPath : 点坐标四个方向的状态(还没有探索过,对应位为0;已经探索过通,正在走的路,对应位为1,不通,对应位为-1)
**/
typedef std::pair<sPoint,sPath> ResultPath;

/* 记录搜索路径的栈 */
std::stack<ResultPath> result;

/* 迷宫的入口与出口定义 */
struct EntranceExit
{
	sPoint m_Entrance;
	sPoint m_Exit;
};


/* 防止回环
  0 --> 0
  |     |
  0 <-- 0
**/
bool DetectLoopBack(sPoint point)
{
	std::stack<ResultPath> loopBack(result);
	while ( !loopBack.empty() )
	{
		if ( (loopBack.top().first.x == point.x)
			&& (loopBack.top().first.y == point.y) )
		{
			return true;
		}
		loopBack.pop();
	}

	return false;
}

void SolveMouse(const char (*pMap)[MAX_COLUMN_SIZE],int m,int n,EntranceExit &entraceExit)
{
	int iPx = entraceExit.m_Entrance.x;
	int iPy = entraceExit.m_Entrance.y;

	//先把入口压栈
	sPath path;
	sPoint point;
	point.x = iPx;
	point.y = iPy;

	result.push(make_pair(point,path));

	while ( (iPx != entraceExit.m_Exit.x) || (iPy != entraceExit.m_Exit.y) )   //还没有到出口,继续探索
	{
		if ( result.empty() )   //没有出口
		{
			cout<<"Mouse Maze don't have a solution"<<endl;
			return ;
		}

		iPx = result.top().first.x;
		iPy = result.top().first.y;

		if ( result.top().second.left == 0 )  //left
		{
			if ( pMap[iPx][iPy-1] == 0 )
			{
				sPoint point;
				point.x = iPx;
				point.y = iPy-1;
				if ( DetectLoopBack(point) )  /* 防止回环 */
				{
					result.top().second.left = -1;   //这个方向不通,为1,记录这个状态为-1
					continue;
				}
				sPath path;
				path.right = 1;   //说明是从left走到right,所以这个点的right标志位为1,表明是路径是从left走到right
				result.push(make_pair(point,path));
			}
			else
			{
				result.top().second.left = -1;   //这个方向不通,为1,记录这个状态为-1
			}
			continue;
		}

		if ( result.top().second.up == 0 )  //up
		{
			if ( pMap[iPx-1][iPy] == 0 )
			{
				sPoint point;
				point.x = iPx-1;
				point.y = iPy;
				if ( DetectLoopBack(point) )  /* 防止回环 */
				{
					result.top().second.up = -1;
					continue;
				}
				sPath path;
				path.down = 1;
				result.push(make_pair(point,path));
			}
			else
			{
				result.top().second.up = -1;
			}
			continue;
		}

		if ( result.top().second.right == 0 )  //right
		{
			if ( pMap[iPx][iPy+1] == 0 )
			{
				sPoint point;
				point.x = iPx;
				point.y = iPy+1;
				if ( DetectLoopBack(point) )  /* 防止回环 */
				{
					result.top().second.right = -1;
					continue;
				}
				sPath path;
				path.left = 1;
				result.push(make_pair(point,path));
			}
			else
			{
				result.top().second.right = -1;
			}
			continue;
		}

		if ( result.top().second.down == 0 )  //down
		{
			if ( pMap[iPx+1][iPy] == 0 )
			{
				sPoint point;
				point.x = iPx+1;
				point.y = iPy;
				if ( DetectLoopBack(point) )  /* 防止回环 */
				{
					result.top().second.down = -1;
					continue;
				}
				sPath path;
				path.up = 1;    //说明是从top元素的上面往下走,所以这个点的up标志位为1,表明是路径是从上面下来
				result.push(make_pair(point,path));
			}
			else
			{
				result.top().second.down = -1;
			}
			continue;
		}

		//尝试了所有的路径,都不成功,回溯
		//找出之前走到这一步的路径,并且标志为-1,因为走不通
		sPath oldPath = result.top().second;
		result.pop();  /* 出栈 */
		if ( oldPath.left == 1 )
		{
			result.top().second.right = -1;
		}
		else if ( oldPath.right == 1 )
		{
			result.top().second.left = -1;
		}
		else if ( oldPath.up == 1 )
		{
			result.top().second.down = -1;
		}
		else if ( oldPath.down == 1 )
		{
			result.top().second.up = -1;
		}
	}
}

/* 输出路径 */
void PrintResult()
{
	while( result.size() )
	{
		cout<<"("<<result.top().first.x<<","<<result.top().first.y<<")"<<endl;
		result.pop();
	}
}

int main()
{
	/* 定义迷宫的出入口 */
	EntranceExit entraceExit;

#if 0 
	/* 测试用例1 */
	entraceExit.m_Entrance.x = 6;
	entraceExit.m_Entrance.y = 9;
	entraceExit.m_Exit.x = 1;
	entraceExit.m_Exit.y = 1;
#endif

	/* 测试用例2 */
	entraceExit.m_Entrance.x = 1;
	entraceExit.m_Entrance.y = 1;
	//entraceExit.m_Exit.x = 6;
	//entraceExit.m_Exit.y = 9;

	/* 测试用例3 */
	entraceExit.m_Exit.x = 4;
	entraceExit.m_Exit.y = 2;

	SolveMouse(cMouseMap,8,11,entraceExit);   /* 解决迷宫 */
	PrintResult();

	std::string sCin;
	std::cin>>sCin;
}

    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/pray90/article/details/42302379
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞