bfs+dfs
题意搞了半天才明白,原来就是给你一个类似于迷宫,#不能走,然后问你从S出发到达E需要多少步。
需要注意的是题目规定了三种走法:dfs(左优先、右优先两种)和bfs(一种)。
那么问题来了,既然前两种方法同样是dfs,经过思考之后发现可以合并。
方位数组dir一定要按照顺序写,以左优先为例:假设人的初始位置为面朝北(默认上北下南),那么此时左为西方,如果西方不能走,人就会调头(此时面朝东),这时左边为北。于是定义左优先的dir数组时应按照顺时针定义,反之,右优先dir数组应按照逆时针定义。这时不难想到,类似于bfs的dir数组,不过可以定义为三维,第一维0表示左优先,1表示右优先
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
struct node
{
int x, y, f;
};
int m, n, sx, sy, ex, ey, vis[50][50];//vis数组为标记数组
char mat[50][50];//用于存储输入的地图
int dir[2][4][2] = {{{0,-1},{-1,0},{0,1},{1,0}},{{0,1},{-1,0},{0,-1},{1,0}}};//方位数组
bool judge(int x, int y)//检查是否符合要求
{
if(x >= 0 && x < m && y >= 0 && y < n && mat[x][y] != '#')
return true;
return false;
}
int dfs(int curdir, int index, int x, int y, int step)//curdir表示当前方位,index为0表示左优先,1表示右优先
{
if(x == ex && y == ey)//到达E
return step;
for(int i = curdir; i < curdir+4; i++)
{
int tx = x+dir[index][i%4][0];
int ty = y+dir[index][i%4][1];
if(judge(tx, ty))
{
dfs((i+3)%4, index, tx, ty, step+1);//当前方位为i%4,如果符合要求,方位应减一
break;
}
}
}
int bfs()//标准的bfs
{
queue<node>q;
node s, e;
memset(vis, 0, sizeof(vis));
s.x = sx;
s.y = sy;
s.f = 0;
q.push(s);
vis[sx][sy] = 1;
while(!q.empty())
{
s = q.front();
q.pop();
for(int i = 0; i < 4; i++)
{
e.x = s.x + dir[0][i][0];
e.y = s.y + dir[0][i][1];
e.f = s.f+1;
if(e.x == ex && e.y == ey)
return e.f;
if(judge(e.x, e.y) && !vis[e.x][e.y])
{
vis[e.x][e.y] = 1;
q.push(e);
}
}
}
return -1;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d %d", &n, &m);
for(int i = 0; i < m; i++)
scanf("%s", mat[i]);
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
{
if(mat[i][j] == 'S')
sx = i,sy = j;
if(mat[i][j] == 'E')
ex = i, ey = j;
}
printf("%d %d %d\n", dfs(0, 0, sx, sy, 1), dfs(0, 1, sx, sy, 1), bfs()+1);//S也算一步
}
return 0;
}