题目链接:UVa 11624 Fire!
要是把人和火一起考虑就会感觉很乱,可以分开考虑,然后计算某个边界点谁先到,人先到就表示人可以逃出去,然后取这些值中那个最小的,这里有一个问题,会不会在途中人和火相遇,然后人比火先到达某个边界点,仔细想想就会发现不会有这种情况,用反证法,如果相遇,那么某个边界点至少是人和火同时到。
所有火都需要都加入队列。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> using namespace std; struct Point { int x, y; Point (int x, int y) : x(x), y(y) {}; Point(){}; }; const int MAX_N = 1000 + 10; int vis1[MAX_N][MAX_N], vis2[MAX_N][MAX_N],dis1[MAX_N][MAX_N], dis2[MAX_N][MAX_N]; char _map[MAX_N][MAX_N]; int fx[4] = {0, 0, 1, -1}; int fy[4] = {1, -1, 0, 0}; int R, C; queue <Point> Q; void BFS1() { int dx, dy; while(!Q.empty()) { Point a = Q.front(); Q.pop(); for(int i = 0; i < 4; i++) { dx = a.x + fx[i], dy = a.y + fy[i]; if(dx >= 0 && dx < R && dy >= 0 && dy < C && _map[dx][dy] != '#' && !vis1[dx][dy]) { dis1[dx][dy] = dis1[a.x][a.y] + 1; vis1[dx][dy] = 1; Q.push(Point(dx, dy)); } } } } void BFS2() { int dx, dy; while(!Q.empty()) { Point a = Q.front(); Q.pop(); for(int i = 0; i < 4; i++) { dx = a.x + fx[i], dy = a.y + fy[i]; if(dx >= 0 && dx < R && dy >= 0 && dy < C && _map[dx][dy] != '#' && !vis2[dx][dy]) { dis2[dx][dy] = dis2[a.x][a.y] + 1; vis2[dx][dy] = 1; Q.push(Point(dx, dy)); } } } } int main() { int T; scanf("%d", &T); while(T--) { memset(vis1, 0, sizeof(vis1)), memset(vis2, 0, sizeof(vis2)); vector <Point> fires; Point Joe; scanf("%d%d", &R, &C); for(int i = 0; i < R; i++) { scanf("%s", _map[i]); for(int j = 0; j < C; j++) { if(_map[i][j] == 'F') fires.push_back(Point(i, j)); else if(_map[i][j] == 'J') Joe.x = i, Joe.y = j; } } int _size = fires.size(); for(int i = 0; i < _size; i++) { Q.push(fires[i]); dis2[fires[i].x][fires[i].y] = 0; vis2[fires[i].x][fires[i].y] = 1; } BFS2(); Q.push(Joe); dis1[Joe.x][Joe.y] = 0; vis1[Joe.x][Joe.y] = 1; BFS1(); int ans = MAX_N * MAX_N; for(int i = 0; i < R; i++) { if(vis1[i][0]) { if(!vis2[i][0] || dis2[i][0] > dis1[i][0]) ans = min(ans, dis1[i][0]); } if(vis1[i][C - 1]) { if(!vis2[i][C - 1] || dis2[i][C - 1] > dis1[i][C - 1]) ans = min(ans, dis1[i][C - 1]); } } for(int j = 0; j < C; j++) { if(vis1[0][j]) { if(!vis2[0][j] || dis2[0][j] > dis1[0][j]) ans = min(ans, dis1[0][j]); } if(vis1[R - 1][j]) { if(!vis2[R - 1][j] || dis2[R - 1][j] > dis1[R - 1][j]) ans = min(ans, dis1[R - 1][j]); } } if(ans == MAX_N * MAX_N) printf("IMPOSSIBLE\n"); else printf("%d\n", ans + 1); } return 0; }