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

关于迷宫问题,求解它的最优解的问题可以使用栈的概念来实现。简单的迷宫如下图
《关于迷宫求解及其最优解的问题》
其中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是该迷宫的最优路径,即是最短长度。

    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/lvyibin890/article/details/78173983
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞