Files
python/C++专题课程/深度优先搜索/深度优先搜索-带完整路径.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

205 lines
4.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
/**
* 功能:声明一个结构体,用来描述移动的横坐标与纵坐标
* 作者:黄海
* 时间:2019-11-17
*/
struct Node {
int x, y;
Node(int a, int b) {
x = a;
y = b;
}
};
//地图大小,一般大开一点方便存储
#define SIZE 100
//右
const int d[4][2] = {
{-1, 0},
{0, -1},
{1, 0},
{0, 1}};
//抽像后的地图,Flase:不可以走,True:可以走。
bool _map[SIZE][SIZE];
//考虑到要图形化输出,先存一份原图:
char pic[SIZE][SIZE];
//是不是访问过?
bool visit[SIZE][SIZE];
//本轮走的路径
vector<Node> path;
//全部路径,都记录下来
vector<vector<Node> > allpath;
//地图 m:行,n:列
int m, n;
//S:出发点,T:终点 ,那么sx,sy就是出发点的坐标,tx,ty就是终点的坐标
int sx, sy, tx, ty;
//深度优先搜索
void dfs(int x, int y) {
//如果找到了终点T,那么x=tx,y=ty
if (x == tx && y == ty) {
//记录这个结点
path.push_back(Node(x, y));
//将路径记录下来
allpath.push_back(path);
//退出准备下一次尝试,这次的任务不是找到就完事了,而是要把所有的可能都找到,然后对比找到最小和路径,所以,需要不停的回退!
path.pop_back();
return;
}
if (!_map[x][y]) return; //不能走就不走
if (visit[x][y]) return; //走过了也不走
//记录走过了这个结点(路径)
path.push_back(Node(x, y));
//标识走了这个结点
dfs(xx, yy);
}
visit[x][y] = 1;
//四个方向进行尝试
for (int i = 0; i < 4; ++i) {
int xx = x + d[i][0], yy = y + d[i][1];
//四个方向进行深度优先探索
//从纸箱中取回,表未没有走过
visit[x][y] = 0;
path.pop_back();
return;
}
/**
* 功能:输出路径
* 作者:黄海
* 时间:2019-11-17
* @param x
*/
void showpath(vector<Node> x) {
char s[SIZE][SIZE];
for (int i = 0; i < n; ++i) {
strcpy(s[i], pic[i]);
}
for (int i = 0; i < x.size(); ++i) {
s[x[i].x - 1][x[i].y - 1] = '+';
}
for (int i = 0; i < m; ++i) puts(s[i]);
printf("step = %d\n", x.size() - 1);
printf("\n");
}
//对比两种方案,如何算是优先级高,即数量少,步骤少。
bool cmp(vector<Node> x, vector<Node> y) {
return x.size() < y.size();
}
int main() {
//读取m:行,n:列
scanf("%d %d", &m, &n);
//所谓初始值,就意味着下面的代码中需要在地图中找到S和T,然后修改sx,sy,tx,ty四个值。
//迷宫入口:
sx = 1; //初始值
sy = 1; //初始值
//迷宫出口:
tx = m; //初始值
ty = n; //初始值
//按行读取数据,共m行
for (int i = 0; i < m; i++) {
scanf("%s", pic[i]); //按行读入地图
char s[SIZE];
strcpy(s, pic[i]);//复制行地图数据到s中
//按列遍历
for (int j = 0; j < n; j++) {
//取出当前值
char c = s[j];
//开始点
if (c == 'S') {
sx = i + 1;
sy = j + 1;
_map[i + 1][j + 1] = true;
}//终点
else if (c == 'T') {
tx = i + 1;
ty = j + 1;
_map[i + 1][j + 1] = true;
}//不能走
else if (c == '#') {
_map[i + 1][j + 1] = false;
} else//可以走
{
_map[i + 1][j + 1] = true;
};
}
}
//深度优先,核心算法
dfs(sx, sy);
//如果没有找到方案
if (allpath.size() == 0) {
printf("没有适用的方案。\n");
} else {
//对数据进行排序,找出步骤最少的方案
sort(allpath.begin(), allpath.end(), cmp);
//输出最佳方案
printf("最佳方案:\n");
showpath(allpath[0]);
//输出其余方案
printf("其余方案:\n");
for (int i = 1; i < allpath.size(); ++i) {
showpath(allpath[i]);
}
//输出方案数
printf("方案数 = %d\n", allpath.size());
}
return 0;
}
/*
https://blog.csdn.net/szdytom/article/details/87537876
-- 下面是测试用例
5 6
....S#
.##...
.#..#.
#..##.
.T....
副另外两个样例:
4 4
S.##
..##
#..#
##.T
5 6
....S#
.##...
.#..#.
#..##.
.T....
*/