今天呢,让我们来用栈求解一下数据结构中的著名问题---迷宫问题
我们先“制造”一个迷宫,把它放在Maze.txt文件中
Maze.txt
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1
1 1 0 1 0 0 0 0 1 1
1 1 0 1 0 1 1 0 1 1
1 1 0 1 1 1 1 1 1 1
1 1 0 0 0 0 0 0 1 1
1 1 0 1 1 1 1 0 1 1
1 1 0 1 1 1 1 0 1 1
1 1 0 1 1 1 1 0 1 1
其中呢,0代表可以走的路,而1呢,则代表的是不可以走的路(墙)
首先呢,我们先来定义一个结构体,用来存储坐标
struct Pos
{
size_t _row;//行
size_t _col;//列
};
接下来呢,我们需要从Maze.txt读入迷宫
void GetMaze(int *maze, size_t N)
{
FILE *fp = fopen("1.txt","r");
if (fp == NULL)
{
throw invalid_argument("Read maze filed");
}
for (size_t i = 0; i < N; ++i)
{
for (size_t j = 0; j < N;)
{
char ch = fgetc(fp);
if (ch == '0' || ch == '1')
{
maze[i*N + j] = ch - '0';
++j;
}
else if (ch == EOF)
{
throw invalid_argument("Maze Error");
}
}
}
}
然后为了方便,我们制定一个函数,用来判断这一步是不是可以走
就是判断这个位置是不是0
bool CheckIsAccess(int *maze, size_t N, Pos next)
{
if (maze[next._row*N + next._col] == 0)
{
return true;
}
return false;
}
利用非递归的方式求解
bool GetMazePath(int *maze, size_t n, Pos entry, stack&path)
{
maze[entry._row*N + entry._col] = 2;
Pos cur,next;
cur = entry;
path.push(entry);
while (!path.empty())
{
cur = path.top();
if (cur._row == N - 1)
{
return true;
}
next = cur;
next._row += 1;
if (CheckIsAccess((int*)maze, N, next) == true)
{
path.push(next);
maze[next._row*N + next._col] = 2;
continue;
}
next = cur;
next._row -= 1;
if (CheckIsAccess((int*)maze, N, next) == true)
{
path.push(next);
maze[next._row*N + next._col] = 2;
continue;
}
next = cur;
next._col += 1;
if (CheckIsAccess((int*)maze, N, next) == true)
{
path.push(next);
maze[next._row*N + next._col] = 2;
continue;
}
next = cur;
next._col -= 1;
if (CheckIsAccess((int*)maze, N, next) == true)
{
path.push(next);
maze[next._row*N + next._col] = 2;
continue;
}
next = cur;
path.pop();
}
return false;
}
利用递归的方式求解
void GetMazePath_R(int *maze, size_t N, Pos entry, stack&path)
{
if (entry._row == N - 1)
{
return;
}
Pos cur,next;
cur = entry;
next = cur;
next._row += 1;
if (CheckIsAccess((int*)maze,N,next) == true)
{
path.push(next);
maze[next._row*N + next._col] = 2;
GetMazePath_R(maze, N, next, path);
}
next = cur;
next._row -= 1;
if (CheckIsAccess((int*)maze, N, next) == true)
{
path.push(next);
maze[next._row*N + next._col] = 2;
GetMazePath_R(maze, N, next, path);
}
next = cur;
next._col += 1;
if (CheckIsAccess((int*)maze, N, next) == true)
{
path.push(next);
maze[next._row*N + next._col] = 2;
GetMazePath_R(maze, N, next, path);
}
next = cur;
next._col -= 1;
if (CheckIsAccess((int*)maze, N, next) == true)
{
path.push(next);
maze[next._row*N + next._col] = 2;
GetMazePath_R(maze, N, next, path);
}
next = cur;
}
对非递归的方法求最短路径
ReMaze表示的是重置迷宫
void ReMaze(int* maze,size_t N)
{
for (size_t i = 0; i < N; ++i)
{
for (size_t j = 0; j < N; ++j)
{
if (maze[i*N + j] != 1)
{
maze[i*N + j] = 0;
}
}
}
}
void TestMaze()
{
try
{
int maze[N][N] = { 0 };
int curmaze[N][N] = { 0 };
GetMaze((int*)maze, N);
stack path,MinPath,empty;
while (GetMazePath((int*)maze, N, { 2, 0 }, path))
{
if (path.size() < MinPath.size()||MinPath.size() == 0)
{
MinPath = path;
}
ReMaze((int*)maze,N);
maze[path.top()._row][path.top()._col] = 1;//将上次的出口改为1
path = empty;
}
cout << "Min path:" << MinPath.size() << endl;
}
catch (exception &e)
{
cout << e.what() << endl;
}
}