You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
python/C++专题课程/回溯算法/迷宫/C++ 用回溯法求解迷宫问题(递归).cpp

104 lines
2.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
/*
一、定义:
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。
但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就
退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
用回溯法求解问题时常使用递归方法进行试探,或使用栈帮助向前试探和回溯。
二、思路:
1.用一个二维数组表示迷宫:
数组中的值如果是1则表示该位置是墙壁不能通行
如果等于0表示该位置是通路
用一个标记数组,标记该位置是否被访问过;
2.迷宫前进的方向:要定义一个结构体存储方向
可能有8个方向东南西南西西北东北
3.给一个入口和出口的坐标,从入口入手:
循环入口的8个方向如果位置通则递归该位置一直递归下去直到到达出口或者所有方向的路不通回溯
*/
// 默认迷宫的行数和列数
const int XLEN = 14, YLEN = 17;
int m, p; // 出口坐标
int maze[XLEN + 2][YLEN + 2]; // 迷宫数组
int mark[XLEN + 2][YLEN + 2]; // 访问标记数组
// 结果体,代表一个二维数组的元素,a和b是x,y方向的偏移
struct Offsets {
int a, b;
};
// 因为不需要输出方向,所以把方向去掉
Offsets direction[8] =
{{-1, 0},
{-1, 1},
{0, 1},
{1, 1},
{1, 0},
{1, -1},
{0, -1},
{-1, -1}
};
// 解决迷宫问题的递归算法
bool seekPath(int x, int y) {
// 从迷宫某一位置[i][j]开始,寻找出口[m][p]的一条路径,如果找到则函数返回true
int i, g, h; // g, h记录位置信息
if (x == m && y == p) // m和p是出口坐标
return true;
// 循环遍历(x, y)的8个方向
for (i = 0; i < 8; i++) {
g = x + direction[i].a;
h = y + direction[i].b;
// 找下一位置寻找通向出口的路径
if (maze[g][h] == 0 && mark[g][h] == 0) { // 如果通且未被访问过
mark[g][h] = 1; // 标记为已访问过
if (seekPath(g, h)) { // 递归试探
cout << "(" << g << ", " << h << ")"; // 逆向输出路径坐标
return true;
}
}
// 回溯,换一个方向再试探通向出口的路径
}
return false; // 找不到通向出口的路径
}
int main(int argc, const char *argv[]) {
//读取数据文件
freopen("./data.txt", "r", stdin);
int i, j, x, y;
// 输入迷宫数据
for (i = 0; i < XLEN; i++) {
for (j = 0; j < YLEN; j++) {
cin >> maze[i][j];
//初始化标记数组
mark[i][j] = 0;
}
}
//输入入口位置坐标
cin >> x >> y;
//输入出口位置坐标
cin >> m >> p;
// 从入口开始
mark[x][y] = 1;
// 调用求解迷宫的递归算法
if (seekPath(x, y)) // 成功
{
cout << "(" << x << ", " << y << ")" << endl;
} else {
cout << "找不到从入口到出口的路径!" << endl;
}
return 0;
}