DFS求左贴墙和右贴墙 BFS求最短路
我用的方向顺序是 上=0 右=1 下=2 左=3
注意要贴墙走,详细见代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <queue>
using namespace std;
const int maxn = 40 + 5;
const int INF = ~0U >> 1;
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, 1, 0, -1};
int T, m, n;
char str[maxn][maxn];
int sx, sy, ex, ey, ans; //sx,sy起点坐标 ex ey终点坐标
int dis[maxn][maxn];
typedef pair<int, int> P;
void dfsL(int x, int y, int type, int d) { // x,y是该点坐标,type是面朝的方向,d是步数
if(x == ex && y == ey) { ans = d; return ; }
int t = type == 0 ? 3 : type - 1;
int nx = dx[t] + x, ny = dy[t] + y; //左边的坐标
if(nx >= 0 && nx < m && ny >= 0 && ny < n && str[nx][ny] != '#') {
int v; if(type == 0) v = 2; if(type == 2) v = 0; if(type == 1) v = 3; if(type == 3) v = 1; //面朝方向的反方向
int c = type == 0 ? 3 : type - 1; //走到左后的时候应该面朝的方向,实际上就是左旋一下
int X = nx + dx[v], Y = ny + dy[v]; //左后方的坐标
if(nx == ex && ny == ey) { ans = d + 1; return ; } //先预判一下左边点能不能到终点 因为下一行代码直接跳了两步 ,所以这里要预判一下
if(X >= 0 && X < m && Y >= 0 && Y < n && str[X][Y] != '#') dfsL(X, Y, c, d + 2); //贴墙走 如果该点的左边的后边可以走的话就要走那里
else dfsL(nx, ny, type, d + 1); //左后不能走 就走左边
}
else {
int v = type == 3 ? 0 : type + 1; //转换以后的方向 右旋一下
dfsL(x, y, v, d); //进角落了 就把方向换一下
}
}
void dfsR(int x, int y, int type, int d) {
if(x == ex && y == ey) { ans = d; return ; }
int t = type == 3 ? 0 : type + 1;
int nx = dx[t] + x, ny = dy[t] + y;
if(nx >= 0 && nx < m && ny >= 0 && ny < n && str[nx][ny] != '#') {
int v; if(type == 0) v = 2; if(type == 2) v = 0; if(type == 1) v = 3; if(type == 3) v = 1;
int c = type == 3 ? 0 : type + 1;
int X = nx + dx[v], Y = ny + dy[v];
if(nx == ex && ny == ey) { ans = d + 1; return ; }
if(X >= 0 && X < m && Y >= 0 && Y < n && str[X][Y] != '#') dfsR(X, Y, c, d + 2);
else dfsR(nx, ny, type, d + 1);
}
else {
int v = type == 0 ? 3 : type - 1;
dfsR(x, y, v, d);
}
}
int bfs() {
queue<P> que;
que.push(P(sx, sy));
dis[sx][sy] = 1;
while(!que.empty()) {
P e = que.front(); que.pop();
if(e.first == ex && e.second == ey) return dis[e.first][e.second];
for(int i = 0; i < 4; ++i) {
int nx = e.first + dx[i], ny = e.second + dy[i];
if(!dis[nx][ny] && nx >= 0 && nx < m && ny >= 0 && ny < n && str[nx][ny] != '#') {
dis[nx][ny] = dis[e.first][e.second] + 1;
que.push(P(nx, ny));
}
}
}
return INF;
}
int main() {
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for(int i = 0; i < m; ++i) {
scanf("%s", str[i]);
for(int j = 0; j < n; ++j) {
if(str[i][j] == 'S') sx = i, sy = j;
if(str[i][j] == 'E') ex = i, ey = j;
}
}
memset(dis, 0, sizeof(dis));
int ty;
if(sx == 0) ty = 2; // 求一下起点应该面朝哪
if(sx == m - 1) ty = 0;
if(sy == 0) ty = 1;
if(sy == n - 1) ty = 3;
dfsL(sx, sy, ty, 1);
printf("%d ", ans);
dfsR(sx, sy, ty, 1);
printf("%d ", ans);
ans = bfs();
printf("%d\n", ans);
}
}
本文介绍了一种使用深度优先搜索(DFS)和广度优先搜索(BFS)解决迷宫问题的方法,通过DFS寻找紧贴墙壁的路径,而BFS则用于寻找从起点到终点的最短路径。

250

被折叠的 条评论
为什么被折叠?



