迷宫需要解决的问题:
1.如何找到通路?
首先在迷宫的入口点进入迷宫,分别别探测上下左右四个方向是否是通路(四个方向不通为1,通为0),如果是可通的方向将此方向的值改为2,接着再走下一个地方,直至走到四个方向中有一个方向是NULL,也就是走到迷宫的边缘,结束。
2.如何解觉没有通路的问题?
最初我们使用死循环来持续判断通路,但是如果迷宫没有通路,就需要判断条件path.empty(),判空条件来控制循环。
3.当迷宫中有多条通路存在时候,如何找最优通路?即最短路。
首先需要将有多条通路的迷宫全部的通路走一遍,才能选择一条较短的通路,则使用GetPathR()函数来寻找多条通路迷宫,这里面使用递归的方式,递归可以自动回溯,其内部实现相当于栈。找最短路径,定义了GetShortPathR()函数,
通过记录走的路径,存入栈中进行位置个数比较,比较出短的那一条通路,把路径存入shortpath中。
递归回溯:
当四周无路可走的时候,栈销毁回退至上一个栈桢,直至到11所在的位置,再向左走至20的位置,四周无路可走,回退至4所在的位置,因探测条件是当0的时候可以走和当比自己本身大的数可走,所以在4的位置走向20的 位置的那条路径,直至出口,然后因递归再回溯到入口的位置。(两层栈桢)
代码如下:
//1.实现迷宫的递归非递归。
//2.实现迷宫的最优解问题。
//3.实现表达式计算问题。
struct Pos
{
size_t _row;
size_t _col;
};
template<size_t M,size_t N>
class Maze
{
public:
//Maze(int maze[][N])//二维数组传参,指定列数//还有其他方式把数组传进去
Maze(int*maze)//问题:为什么这里可以这么传参?
{
for (size_t i = 0; i < M; ++i)
{
for (size_t j = 0; j < N; ++j)
{
//_maze[i][j] = maze[i][j];
_maze[i][j] = maze[i*N + j];//问题:为什么这里可以乘以N来计算?
}
}
}
void Print()//打印迷宫
{
for (size_t i = 0; i < M; ++i)
{
for (size_t j = 0; j < N; ++j)
{
cout << _maze[i][j] << " ";
}
cout << endl;
}
cout << endl;
if (!shortPath.empty())//打印出具体路径
{
cout << "最短路径长度" << shortPath.size() << endl;
cout << "最短路径:出口";
stack<Pos>tmp = shortPath;//栈支持拷贝构造,是深拷贝
while (!tmp.empty())
{
Pos& top = tmp.top();
printf("[%d,%d]<-", top._row, top._col);
tmp.pop();
}
cout << "入口" << endl;
}
}
//bool CheckAccess(Pos next)//判断是否可以通
//{
// if (next._row < M && next._col < N
// && _maze[next._row][next._col] == 0)
// {
// return true;
// }
// return false;
//}
bool CheckAccess(Pos cur, Pos next)//判断是否可以通
{
if ((next._row < M && next._col < N) // 检查nxet合不合法
&& (_maze[next._row][next._col] == 0 //检查next是不是通路
|| _maze[next._row][next._col] > _maze[cur._row][cur._col]))//通路---比所在位置的本身大的值得位置
{
return true;
}
return false;
}
//bool GetPath(Pos entry)
//{
// Pos cur, next;
// cur = entry;
// stack<Pos> path;
// path.push(entry);
// while (!path.empty())//如果是死循环,当迷宫没有通路的时候就会程序崩溃。
// {
// cur = path.top();//cur 试探上下左右的方向
// _maze[cur._row][cur._col] = 2;//continue上来的
// if (cur._row == M - 1)
// {
// return true;
// }
// next = cur;
// next._row -= 1;//上
// if (CheckAccess(next))
// {
// path.push(next);//假如可通就continue返回之前再探测其他方向
// continue;
// }
// next = cur;
// next._row += 1;//下
// if (CheckAccess(next))
// {
// path.push(next);
// continue;
// }
// next = cur;
// next._col -= 1;//左
// if (CheckAccess(next))
// {
// path.push(next);
// continue;
// }
// next = cur;
// next._col += 1;//右
// if (CheckAccess(next))
// {
// path.push(next);
// continue;
// }
// //回溯
// path.pop();//四个方向都不通则把这个栈点pop出去
// }
// return false;
//}
//找多条通路(递归)
void GetPathR(Pos entry)
{
_maze[entry._row][entry._col] = 2;//标记走过的位置
if (entry._row == M - 1)
{
cout << "找到一个出口" << "[" << entry._row << "," << entry._col << "]" << endl;
return;//这里的return不是直接回到最开始,而是返回上一个位置
}
Pos next;
next = entry;
next._row -= 1;//上
if (CheckAccess(next))
{
GetPathR(next);//如果找一条通路,这里的返回值是true
}
next = entry;
next._row += 1;//下
if (CheckAccess(next))
{
GetPathR(next);
}
next = entry;
next._col += 1;//右
if (CheckAccess(next))
{
GetPathR(next);
}
next = entry;
next._col -= 1;//左
if (CheckAccess(next))
{
GetPathR(next);
}
path.pop()
}
找出最短路径
//void GetShortPath(Pos entry,stack<Pos>&path)
//{
// path.push(entry);
//
// _maze[entry._row][entry._col] = 2;//标记走过的位置为2
// if (entry._row == M-1)
// {
// if (shortPath.empty() || path.size() < shortPath.size())
// {
// shortPath = path;//shortPath存的就是最短路径
// }
// cout << "找到一个出口" << "[" << entry._row << "," << entry._col << "]" << endl;
// //return;//这里的return不是直接回到最开始,而是返回上一个位置
// }
// Pos next;
// next = entry;
// next._row -= 1;//上
// if (CheckAccess(entry, next))
// {
// GetShortPath(next, path);//如果找一条通路,这里的返回值是true
// }
// next = entry;
// next._row += 1;//下
// if (CheckAccess(entry, next))
// {
// GetShortPath(next, path);
// }
// next = entry;
// next._col -= 1;//左
// if (CheckAccess(entry, next))
// {
// GetShortPath(next, path);
// }
// next = entry;
// next._col += 1;//右
// if (CheckAccess(entry, next))
// {
// GetShortPath(next, path);
// }
// path.pop();
//}
void GetShortPathR(Pos entry, stack<Pos>&path)
{
path.push(entry);
if (entry._row == M - 1)
{
if (shortPath.empty() || path.size() < shortPath.size())
{
shortPath = path;//shortPath存的就是最短路径
}
cout << "找到一个出口" << "[" << entry._row << "," << entry._col << "]" << endl;
//return;//这里的return不是直接回到最开始,而是返回上一个位置
}
//需要顺时针走
Pos next;
next = entry;
next._row -= 1;//上
if (CheckAccess(entry, next))
{
_maze[next._row][next._col] = _maze[entry._row][entry._col] + 1;//标记走过的位置分别是2,3,4,5...
GetShortPathR(next, path);//如果找一条通路,这里的返回值是true
}
next = entry;
next._col += 1;//右
if (CheckAccess(entry, next))
{
_maze[next._row][next._col] = _maze[entry._row][entry._col] + 1;//标记走过的位置分别是2,3,4,5...
GetShortPathR(next, path);
}
next = entry;
next._row += 1;//下
if (CheckAccess(entry, next))
{
_maze[next._row][next._col] = _maze[entry._row][entry._col] + 1;//标记走过的位置分别是2,3,4,5...
GetShortPathR(next, path);
}
next = entry;
next._col -= 1;//左
if (CheckAccess(entry, next))
{
_maze[next._row][next._col] = _maze[entry._row][entry._col] + 1;//标记走过的位置分别是2,3,4,5...
GetShortPathR(next, path);
}
path.pop();
}
protected:
int _maze[M][N];
stack<Pos>shortPath;
};
void TestMaze()
{
//int mazeArray[10][10] = //无环迷宫
//{
// { 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, 1, 1, 1, 1, 1, 1 },
// { 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 },
// { 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
// { 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
// { 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
// { 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 },
// { 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 }
//};
int mazeArray[10][10] = //有环迷宫
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 2, 0, 0, 0, 0, 0, 0, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 }
};
/*Maze<10, 10> maze(mazeArray);*/ //接收int maze[][N]的传参方式
Maze<10, 10>maze((int*)mazeArray); //接收int* maze的传参方式
maze.Print();
Pos entry = { 2, 0 };
//if (maze.GetPath(entry))
//{
// cout << "找到通路了" << endl;
//}
//else
//{
// cout << "没有找到通路" << endl;
//}
//maze.GetPathR(entry);
stack<Pos> path;
maze.GetShortPathR(entry,path);
maze.Print();
}
测试如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
#include<stack>
using namespace std;
#include"Maze.h"
#include"Calculate.h"
//int main()
//{
// TestMaze();
// system("pause");
// return 0;
//}
int main()
{
vector<Cell> exp;
//exp.push_back(Cell(OP_NUM, 2));
//exp.push_back(Cell(OP_NUM, 3));
//exp.push_back(Cell(OP_NUM, 4));
//exp.push_back(Cell(OP_SYMBOL, '*'));
//exp.push_back(Cell(OP_SYMBOL, '-'));
//exp.push_back(Cell(OP_NUM, 5));
//exp.push_back(Cell(OP_SYMBOL, '+'));
exp.push_back(Cell(OP_NUM, 2));
exp.push_back(Cell(OP_SYMBOL, OP_SUB));
exp.push_back(Cell(OP_NUM, 3));
exp.push_back(Cell(OP_SYMBOL, OP_MUL));
exp.push_back(Cell(OP_NUM, 4));
exp.push_back(Cell(OP_SYMBOL, OP_ADD));
exp.push_back(Cell(OP_NUM, 5));
//Calculator ec(exp);
//cout << "计算结果是:" << ec.Count() << endl;
/* Cell exp[] =
{
{OP_NUM, 2},
{OP_NUM, 3},
{OP_NUM, 4},
{OP_SYMBOL, OP_MUL},
{OP_SYMBOL, OP_SUB},
{OP_NUM, 5},
{OP_ADD, OP_ADD},
};*/
//
Calculator cal(exp);
cout << "计算结果:" << cal.Count() << endl; //
system("pause");
return 0;
}