回溯法写迷宫
迷宫规则:
- 唯一出口和入口,本次规定入口为左上角,出口为右下角
- 如下图所示,红色方块为墙,不能走,白色区域可以走
- 红色方块标志为1,白色区域标志为0
- 迷宫矩阵大小可以自己定义,如下定义的是5*5矩阵
- 要求找到最短路径并且输出路径坐标
回溯法
回溯法思路:
是将问题转化为树或者图的形式,然后利用深度优先搜索进行遍历,然后再遍历过程中记录所有可执行解和最优解
回溯法的实现方式:递推法&递归法
具体有关回溯法介绍下一篇博客有详细介绍
解决步骤
1.首先将当前点加入路径,并设置为已走
2.判断当前点是否为出口,如果是将最短路径和当前路径比较,将最短路径输出;跳转到4
3.依次判断当前点的上、下、左、右四个点是否可走,如果可走则递归走该点
4.该点退出当前路径,设置为可走
代码分析
- 自定义函数:Mazeskr
void Mazeskr(int i, int j) {
maze[i][j] = 1;//表示当前节点已走,不可再走
path_new.push_back({ i, j });//将当前节点加入到路径中
if (i == n - 1 && j == m - 1) //判断是否到达终点
if (path_best.empty() || path_shortest.size() > path_new.size())
path_new= path_new;
if (i >= 1 && maze[i - 1][j] == 0)//探索向上走是否可行
Mazeskr(i - 1, j);
if (i + 1 < n && maze[i + 1][j] == 0)//探索向下走是否可行
Mazeskr(i + 1, j);
if (j >= 1 && maze[i][j - 1] == 0)//探索向左走是否可行
Mazeskr(i, j - 1);
if (j + 1 < m && maze[i][j + 1] == 0)//探索向右走是否可行
Mazeskr(i, j + 1);
maze[i][j] = 0; //恢复没走
path_new.pop_back(); //尾删,去掉这个路径结点
}
2.定义全局变量和主函数
#include<iostream>
#include<vector>
//由于矩阵变量不仅要在主函数中调用
//也要在自定义函数中使用,所以可定义为全局变量
int n,m;
using namespace std;
vector<vector<int> > maze;
vector<vector<int> >path_new;//当前路径,第一维存储路径坐标
vector<vector<int> >path_shortest;//最短路径
int main()
{
while(cin>>n>>m){
maze = vector<vector<int>>(N, vector<int>(M, 0));
path_new.clear(); //情况之前的数据
path_shortest.clear();
for (auto &i : maze)
for (auto &j : i)
cin >> j;
Mazeskr(0, 0);//回溯寻找迷宫最短通路
for (auto i : path_best)
cout << '[' << i[0] << ',' << i[1] << ']' << endl;//输出通路
}
system("pause");
return 0;
}