关于迷宫求解及其最优解的问题

来源:互联网 发布:淘宝联盟导出excel后 编辑:程序博客网 时间:2024/05/14 16:12

关于迷宫问题,求解它的最优解的问题可以使用栈的概念来实现。简单的迷宫如下图
这里写图片描述
其中0表示可以走,1表示不能走,显然可见,若是以(3,1)点为入口,则有两个出口分别是(10,3)和(10, 8)。而两个出口的路径长度是不同的。这就产生了迷宫最优解的问题。
这里写图片描述

下面附上代码,我们寻找下一个位置是否可走的顺序是顺时针顺序,即上右下左。

#pragma once#include<iostream>using namespace std;//#define _CRT_SECURE_NO_WARNINGS#pragma warning(disable:4996)#include<assert.h>#include<stdio.h>#include<stack>struct Pos{    int _row;    int _col;};template<size_t M,size_t N>class Maze{public:    Maze()    {        FILE* fout = fopen("MazeMap.txt", "r");        assert(fout);        for (size_t i = 0; i < M; ++i)        {            for (size_t j = 0; j < N;)            {                char ch = fgetc(fout);                if (ch == '1' || ch == '0')                //构建一个以文字内数字为元素的二维数组,1表示不可走,0表示可走                {                    _maze[i][j] = ch - '0';                    ++j;                }            }        }    }    bool CheckAccess(Pos pos)//检查下一个位置是否可以走    {        if ((pos._row<M)&&(pos._col<N)&&(_maze[pos._row][pos._col] == 0))        {            return true;        }        return false;    }    bool GetMazePathR(Pos cur)//递归走    {        _maze[cur._row][cur._col] = 2;//用2表示走过的位置来记录        //找到出口        if (cur._row == M - 1)        {            return true;        }        //探测        Pos next = cur;        //上        next._row -= 1;        if (CheckAccess(next))        {            if (GetMazePathR(next))                return true;        }        //右        next = cur;        next._col += 1;        if (CheckAccess(next))        {            if (GetMazePathR(next))                return true;        }        //下        next = cur;        next._row += 1;        if (CheckAccess(next))        {            if (GetMazePathR(next))                return true;        }        //左        next = cur;        next._col -= 1;        if (CheckAccess(next))        {            if (GetMazePathR(next))                return true;        }        return false;    }    bool GetMazePathNonR(Pos entry)//非递归走,用回溯的方法    {        stack<Pos> path;        path.push(entry);//先将入口push到栈中        while (!path.empty())        {            Pos cur = path.top();            _maze[cur._row][cur._col] = 2;//用2表示走过的位置来记录            Pos next = cur;            if (cur._row == M-1)            {                return true;            }            //向上探测            --next._row;            if (CheckAccess(next))            {                path.push(next);                continue;            }            next = cur;//如果不能走,让next回到初始的cur的位置            //向右探测            ++next._col;            if (CheckAccess(next))            {                path.push(next);                continue;            }            next = cur;            //向下探测            ++next._row;            if (CheckAccess(next))            {                path.push(next);                continue;            }            next = cur;            //向左探测            --next._col;            if (CheckAccess(next))            {                path.push(next);                continue;            }            next = cur;            _maze[cur._row][cur._col] = 3;            //如果一个if条件都没有进,那么该位置是死胡同,不能走,用3来表示            path.pop();//将该位置pop出栈        }        return false;    }    bool CheckAccess(Pos cur,Pos next)    //与上一个CheckAccess函数形成重载    {        if ((next._row>=M) || (next._col>=N) )        {            return false;        }        if ((_maze[next._row][next._col] == 0)         || (_maze[next._row][next._col]> (_maze[cur._row][cur._col] + 1)))        {            return true;        }        return false;    }    void GetMazeShortPathR(Pos cur, stack<Pos>& paths, stack<Pos>& shortpaths)    //求解出口的最短路径    {        paths.push(cur);        //找到出口        if (cur._row == M - 1)        {            if (shortpaths.empty()||(shortpaths.size()>paths.size()))            {                shortpaths = paths;            }            return;        }        //探测        Pos next = cur;        //上        next._row -= 1;        if (CheckAccess(cur,next))        {            _maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;            GetMazeShortPathR(next, paths, shortpaths);        }        //右        next = cur;        next._col += 1;        if (CheckAccess(cur, next))        {            _maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;            GetMazeShortPathR(next, paths, shortpaths);        }        //下        next = cur;        next._row += 1;        if (CheckAccess(cur,next))        {            _maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;            GetMazeShortPathR(next, paths, shortpaths);        }        //左        next = cur;        next._col -= 1;        if (CheckAccess(cur,next))        {            _maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;            GetMazeShortPathR(next, paths, shortpaths);        }        paths.pop();    }    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;    }protected:    int _maze[M][N];};

三个测试的测试代码及测试结果如下

void TestMaze(){    Maze<10, 10> m;    m.Print();    Pos entry = {2,0};    stack<Pos> paths, shortpaths;    //cout << "找到出口?" << m.GetMazePathR(entry) << endl;    //cout << "找到出口?" << m.GetMazePathNonR(entry) << endl;    m.GetMazeShortPathR(entry, paths, shortpaths);    m.Print();}

递归走
这里写图片描述

非递归走,我们为了突出效果,把(10,8)的出口给封掉,变成不可走
这里写图片描述
可以看到,以上两种因为查找下一位置的顺序的原因,只找到了一个出口,那么要找出最优的路径,就必须把所有的路径长度求出来进行比较,用3表示满足不了需求,我们可用没走一步就+1的方法来表示。
这里写图片描述
两条路径的长度分别是9和14,显然9是该迷宫的最优路径,即是最短长度。

原创粉丝点击