这道题应该是我做过的最麻烦也是最有意思的一道BFS了,一般的BFS的vis数组表示的只是某个坐标是否走过,而这个题vis表示的东西就比较多了,分别是两个坐标,颜色,朝向,那vis数组就应该是四维的了。
每个状态可以转移到三种状态,不是一般BFS的四个方向,而是有特别含义的三个方向。
如果不单步走(比如可以后转,算两步),也可以用优先队列来实现。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
using namespace std;
const int MAX_N = 25 + 5;
const int INF = (1 << 28);
struct Point
{
int x, y, d, c;
Point (int x, int y, int d, int c) : x(x), y(y), d(d), c(c) {};
Point () {};
};
int vis[MAX_N][MAX_N][4][5], dis[MAX_N][MAX_N][4][5];
char _map[MAX_N][MAX_N];
int n, m, res;
queue <Point> Q;
void BFS()
{
int dx, dy, dd, dc;
while(!Q.empty())
{
Point a = Q.front();
Q.pop();
dd = a.d, dc = (a.c + 1) % 5;
if(a.d == 0)
dx = a.x, dy = a.y - 1;
else if(a.d == 1)
dx = a.x - 1, dy = a.y;
else if(a.d == 2)
dx = a.x, dy = a.y + 1;
else if(a.d == 3)
dx = a.x + 1, dy = a.y;
if(dx >= 0 && dy >= 0 && dx < n && dy < m && _map[dx][dy] != '#' && !vis[dx][dy][dd][dc])
{
vis[dx][dy][dd][dc] = 1;
dis[dx][dy][dd][dc] = dis[a.x][a.y][a.d][a.c] + 1;
if(_map[dx][dy] == 'T' && dc == 0)
{
res = dis[dx][dy][dd][dc];
return;
}
Q.push(Point(dx, dy, dd, dc));
}
dd = (a.d + 1) % 4, dc = a.c, dx = a.x, dy = a.y;
if(dx >= 0 && dy >= 0 && dx < n && dy < m && _map[dx][dy] != '#' && !vis[dx][dy][dd][dc])
{
vis[dx][dy][dd][dc] = 1;
dis[dx][dy][dd][dc] = dis[a.x][a.y][a.d][a.c] + 1;
if(_map[dx][dy] == 'T' && dc == 0)
{
res = dis[dx][dy][dd][dc];
return;
}
Q.push(Point(dx, dy, dd, dc));
}
dd = (a.d - 1 + 4) % 4, dc = a.c, dx = a.x, dy = a.y;
if(dx >= 0 && dy >= 0 && dx < n && dy < m && _map[dx][dy] != '#' && !vis[dx][dy][dd][dc])
{
vis[dx][dy][dd][dc] = 1;
dis[dx][dy][dd][dc] = dis[a.x][a.y][a.d][a.c] + 1;
if(_map[dx][dy] == 'T' && dc == 0)
{
res = dis[dx][dy][dd][dc];
return;
}
Q.push(Point(dx, dy, dd, dc));
}
}
}
int main()
{
//freopen("in.txt", "r", stdin);
int _case = 0;
while(scanf("%d%d", &n, &m) , n + m)
{
res = INF;
memset(vis, 0, sizeof(vis));
Point _start;
for(int i = 0; i < n; i++)
{
scanf("%s", _map[i]);
for(int j = 0; j < m; j++)
{
if(_map[i][j] == 'S')
{
_start = Point(i, j, 1, 0);
vis[i][j][1][0] = 1;
dis[i][j][1][0] = 0;
}
}
}
Q.push(_start);
BFS();
if(_case != 0)
{
printf("\n");
while(!Q.empty())
Q.pop();
}
printf("Case #%d\n", ++_case);
if(res == INF)
printf("destination not reachable\n");
else
printf("minimum time = %d sec\n", res);
}
return 0;
}