迷宫问题
来源:互联网 发布:php 去掉双引号 编辑:程序博客网 时间:2024/06/09 17:30
迷宫需要解决的问题:
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; }
阅读全文
0 0
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题...
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- 迷宫问题
- Java并发工具类之CountDownLatch
- JavaSE基础08内部类
- 专栏|在U盘中运行深度神经网络?详解英特尔Movidius神经元计算棒
- JavaSe_day08
- PULL Adapter
- 迷宫问题
- unity学习笔记--unity的一些学习资料推荐
- js 事件对象(一)
- 发邮件如何隐藏IP地址
- React Native构建官方example学习笔记
- viewpage
- java同名全局变量和局部变量的问题
- 天然气分布式能源系统在数据中心领域的应用
- html中播放avi格式的视频文件