回溯法求迷宫

首先我们先“创建”一个迷宫,把其放在Mazemap.txt文件中。
0代表可以走的路,1表示不通的路。

首先定义一个结构体,用来存储坐标

template
class Maze
{
public:
    Maze(int maze[M][N])
    {
        for (size_t i = 0; i < M; ++i)
        {
            for (size_t j = 0; j < N; ++j)
            {
                _maze[i][j] = maze[i][j];
            }
        }
    }

    struct Pos
    {
        int _row; // 行
        int _col; // 列
    };

构造一个函数,判断可不可以走下去,其位置是否是0

bool CheckAccess(Pos next)
    {
        if ((next._row >= 0 && next._row < M)
            &&(next._col >= 0 && next._col <= N)
            && _maze[next._row][next._col] == 0)
        {
            return true;
        }

        return false;
    }

接下来求解
<非递归法>

bool GetMazePath(Pos entry)
    {
        stack paths;
        paths.push(entry);

        while (!paths.empty())
        {
            // 栈顶的坐标就是当前位置
            Pos cur = paths.top();
            _maze[cur._row][cur._col] = 2;

            // 已经到出口
            if (cur._row == M-1)
            {
                return true;
            }

            // 试探四个方向
            // 上
            Pos next = cur;
            next._row -= 1;
            if(CheckAccess(next))
            {
                paths.push(next);
                continue;
            }


            // 右
            next = cur;
            next._col += 1;
            if(CheckAccess(next))
            {
                paths.push(next);
                continue;
            }


            // 下
            next = cur;
            next._row += 1;
            if(CheckAccess(next))
            {
                paths.push(next);
                continue;
            }

            // 左
            next = cur;
            next._col -= 1;
            if(CheckAccess(next))
            {
                paths.push(next);
                continue;
            }

            Pos back = paths.top();
            _maze[back._row][back._col] = 3;
            paths.pop();
        }

        return false;
    }

<递归法>

bool GetMazePathR(Pos entry)
    {
        Pos cur = entry;
        _maze[cur._row][cur._col] = 2;
        // 已经找到出口
        if (entry._row == N-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;
        }

        // 
        _maze[cur._row][cur._col] = 3;
        return false;
    }

继续构建一个函数用来检测。

bool CheckAccess(Pos next, Pos cur)
    {
        if ((next._row >= 0 && next._row < M)
            &&(next._col >= 0 && next._col <= N))
        {
            if (_maze[next._row][next._col] == 0)
            {
                return true;
            }
            else if (_maze[next._row][next._col] == 1)
            {
                return false;
            }
            else
            {
                return _maze[next._row][next._col] > _maze[cur._row][cur._col]+1;
            }
        }
        else
        {
            return false;
        }
    }

接下来求最短路径

void GetShortPath(Pos entry,
        stack& path, stack& shortPath)
    {
        Pos cur = entry;
        path.push(cur);

        // 已经找到出口
        if (entry._row == N-1)
        {
            Print();
            if (shortPath.empty() || path.size() < shortPath.size())
            {
                shortPath = path;
            }
        }

        Pos next = cur;

        // 上
        next._row -= 1;
        if (CheckAccess(next, cur))
        {
            // 子问题
            _maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;
            GetShortPath(next, path, shortPath);            
        }

        // 右
        next = cur;
        next._col += 1;
        if (CheckAccess(next, cur))
        {
            _maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;
            GetShortPath(next, path, shortPath);            
        }

        // 下
        next = cur;
        next._row += 1;
        if (CheckAccess(next, cur))
        {
            _maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;
            GetShortPath(next, path, shortPath);            
        }

        // 左
        next = cur;
        next._col -= 1;
        if (CheckAccess(next, cur))
        {
            _maze[next._row][next._col] = _maze[cur._row][cur._col] + 1;
            GetShortPath(next, path, shortPath);            
        }

        path.pop();
    }

其余代码如下

protected:
    int _maze[M][N];
};

void ReadMaze(int maze[10][10])
{
    FILE* fout = fopen("MazeMap.txt", "r");
    assert(fout);

    for (size_t i = 0; i < 10; ++i)
    {
        for (size_t j = 0; j < 10;)
        {
            char ch = fgetc(fout);
            if (ch == '0' || ch == '1' || ch == '2')
            {
                maze[i][j] = ch - '0';
                ++j;
            }
        }
    }
}

void TestMaze()
{
    // 如何动态创建一个二维数组?
    // 跟静态的二维数组的区别是什么?
    // 迷宫的最优解--多条路径中最短的一条?
    int maze[10][10];
    ReadMaze(maze);

    Maze<10, 10> m(maze);
    Maze<10, 10>::Pos entry;
    entry._row = 2;
    entry._col = 0;
    //m.GetMazePath(entry);
    //cout<

    stack::Pos> path, shortPath;
    m.GetShortPath(entry, path, shortPath);
    //m.Print();
}

迷宫求解对于数据结构的学习有很大帮助,这段代码我花费了 一周多时间来编写和理解,刚开始有些点还是不是完全理解 ,经过每天多次思考测试,最后写出了。希望和我一样正在学习这部分的同学可以多多思考,温故而知新。

你可能感兴趣的:(数据结构)