题目大意:从迷宫入口S走到出口E,可以沿着人物当前左手边的墙走,也可以沿着右手边的墙走,问分别经过的方块个数,以及S到E的最短路径
输入:迷宫个数n
迷宫宽度(列数)w 迷宫高度(行数)h (w>=3,h<=40)
第i行迷宫的布局(#表示墙 .表示空路,迷宫四面除了入口S和出口E都是墙,SE至少间隔一个墙,且不在角落)
输出:(第i个迷宫) 沿着左边墙走经过的方块个数 沿着右边墙走经过的方块个数 S到E所经过方块的最短路
分析:前两问用dfs,最后一问是bfs
(一)先说dfs
沿着左边墙走的dfs顺序为左上右下,方向数组为:← ↑ → ↓ 0 1 2 3
沿着右边墙走的dfs顺序为右上左下,方向数组为: →↑ ← ↓ 0 1 2 3
dl、dr分别为沿着左边墙和沿着右边墙走时,行列坐标的变化数组
深度优先搜索函数dfs(sx,sy,d1/d2,1,dl/dr):意味着以(sx,sy)为当前起点,以d为当前方向,步数为1开始递归搜索
d1、d2表示当前方向,d1是沿着左手边的墙走,d2是沿着右手边的墙走
每次dfs分别转向四个方向,判断向这个方向走一步是否能走,越界或撞墙就换方向,到终点就退出,否则就意味着能走,继续dfs
(二)再说bfs
求最短路径,用队列bfs,注意添加vis[][]数组辅助判断是否已经访问过该位置
不断从队列中弹出结点,以弹出结点为当前起始位置,判断是否到达终点,已到达就退出,没到达就bfs转向四个方向,判断这个方向走一步是否能走,越界、撞墙或已经走过这个位置就换方向,否则就意味着能走,将这个位置入队
代码:转载自https://www.cnblogs.com/shenben/p/5628296.html
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
const int maxn=100+10;
int dx[]={0,-1,0,1};
int dy[]={-1,0,1,0};
int dl[][2]={{0,-1},{-1,0},{0,1},{1,0}};
int dr[][2]={{0,1},{-1,0},{0,-1},{1,0}};
int sx,sy,ex,ey,n,m;
char g[maxn][maxn];
struct node{
int x,y,s;
node (int x=0,int y=0,int s=0):x(x),y(y),s(s){}
};
int dfs(int x,int y,int d,int step,int dir[][2]) {
for(int i=0;i<4;i++){
int j=((d-1+4)%4+i)%4;//分别转向四个方向后的当前方向
int nx=x+dir[j][0];
int ny=y+dir[j][1];
if(nx==ex&&ny==ey) return step+1;
if(nx<0||ny<0||nx>n||ny>m) continue;
if(g[nx][ny]=='#') continue;
return dfs(nx,ny,j,step+1,dir);
}
}
int bfs(int sx,int sy) {
bool vis[maxn][maxn];
memset(vis,false,sizeof(vis));
queue<node>que;
que.push((node){sx,sy,1});
vis[sx][sy]=true;
while(!que.empty()) {
node p=que.front();que.pop();
if(p.x==ex&&p.y==ey) return p.s;
node np;
for(int d=0;d<4;d++) {
np.x=p.x+dx[d];
np.y=p.y+dy[d];
np.s=p.s+1;
if(np.x<0||np.x>n||np.y<0||np.y>m) continue;
if(vis[np.x][np.y]) continue;
if(g[np.x][np.y] !='#'){
vis[np.x][np.y]=true;
que.push(np);
}
}
}
return -1;
}
int main()
{
int T,d1,d2;
scanf("%d",&T);
while(T--) {
scanf("%d%d",&m,&n);//迷宫列数、行数
for(int i=0;i<n;i++){
scanf("%s",g[i]);
for(int j=0;j<m;j++){
if(g[i][j]=='S'){sx=i;sy=j;}
else if(g[i][j]=='E'){ex=i;ey=j;}
}
}
if(sx==0) {d1=3;d2=3;}//由于沿着左边墙和沿着右边墙走的方向数组不同,d1d2不同
else if(sx==n-1) {d1=1;d2=1;}
else if(sy==0) {d1=2;d2=0;}
else if(sy==m-1) {d1=0;d2=2;}
printf("%d ",dfs(sx,sy,d1,1,dl));
printf("%d ",dfs(sx,sy,d2,1,dr));
printf("%d\n",bfs(sx,sy));
}
return 0;
}