没有对程序进行优化,使用最原始的想法进行编程。
/*
迷宫问题的深度优先回溯法---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;
}