|
|
#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;
|
|
|
}
|