迷宫问题

来源:互联网 发布: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; } 
原创粉丝点击