先上代码。样例可以跑过,测试数据 AC38 WA19。
#include <iostream>
#include <queue>
#define MAXN 1001
using namespace std;
struct node {int x, y, dir;}; // 0: any; 1: ver; 2: hor
bool vis[MAXN][MAXN];
char g[MAXN][MAXN];
int dis[MAXN][MAXN];
int n, m, sx, sy, fx, fy;
int dxV[2] = {-1, 1}, dxH[2] = {0, 0}, dx[4] = {-1, 1, 0, 0};
int dyV[2] = {0, 0}, dyH[2] = {-1, 1}, dy[4] = {0, 0, -1, 1};
void bfs()
{
queue<node> q;
q.push((node){sx, sy, 0});
vis[sx][sy] = true;
dis[sx][sy] = 0;
while (!q.empty())
{
node u = q.front();
q.pop();
for (int i = 0; i < (u.dir == 0 ? 4 : 2); i++)
{
int kx, ky;
if (u.dir == 0)
kx = u.x + dx[i], ky = u.y + dy[i];
else if (u.dir == 1)
kx = u.x + dxV[i], ky = u.y + dyV[i];
else if (u.dir == 2)
kx = u.x + dxH[i], ky = u.y + dyH[i];
if (kx >= 1 && kx <= n && ky >= 1 && ky <= m && g[kx][ky] != '#' && !vis[kx][ky])
{
int kdir;
if (u.dir == 0)
kdir = i < 2 ? 2 : 1;
else if (u.dir == 1)
kdir = 2;
else if (u.dir == 2)
kdir = 1;
q.push((node){kx, ky, kdir});
dis[kx][ky] = dis[u.x][u.y] + 1;
vis[kx][ky] = true;
if (kx == fx && ky == fy)
{
cout << dis[kx][ky] << endl;
return ;
}
}
}
}
cout << -1 << endl;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> g[i][j];
if (g[i][j] == 'S')
sx = i, sy = j;
else if (g[i][j] == 'G')
fx = i, fy = j;
}
}
bfs();
return 0;
}
大概思路就是广搜。
其中 node 结构体中的 dir 可以为 0、1、2, 0 代表下一步可以走任意的方向(仅存在于第一步),1 代表下一步只能走垂直方向,2 代表下一步只能走水平方向。
对于几个偏移量数组,dxV 和 dyV 表示垂直方向的偏移量,dxH 和 dyH 表示水平方向的偏移量,dx 和 dy 表示四个方向的偏移量。
内层循环根据下一步可走的方向来判断要遍历的数组。
剩下的就是一些常规的广搜操作。
那么请求解答:样例都是可以过的,而且主逻辑似乎没有问题,那么哪里写的有瑕疵?对于第一次就走四个方向,会不会对之后走的步骤有影响?别人有一种解法是第一遍只走水平或垂直(当成参数给出),然后跑两遍广搜,和我的方法有什么区别?