题目链接:https://vjudge.net/problem/UVA-11624
题意:一个迷宫,可能有一个或者多个地方着火了,每过1个时间消耗,火会向四周蔓延,问Joe能不能逃出迷宫,只要走出迷宫边界就算逃出,火和Joe都不能透过墙。
思路:人和火源分别跑bfs,人一张地图,火源一张地图,跑各自能到达点的时间,火源可能有多个,
最后只需要判断迷宫的四个边中人和火源的时间消耗来得出最小答案,出不去输出“IMPOSSIBLE”,思路比较简单,代码稍微复杂点。
1 #include <iostream> 2 #include <cstring> 3 #include<vector> 4 #include<string> 5 #include <cmath> 6 #include <map> 7 #include <queue> 8 #include <algorithm> 9 using namespace std; 10 11 #define inf (1LL << 31) - 1 12 #define rep(i,j,k) for(int i = (j); i <= (k); i++) 13 #define rep__(i,j,k) for(int i = (j); i < (k); i++) 14 #define per(i,j,k) for(int i = (j); i >= (k); i--) 15 #define per__(i,j,k) for(int i = (j); i > (k); i--) 16 17 const int N = 1010; 18 int mv_x[] = { 0, 0, -1, 1 }; 19 int mv_y[] = { 1, -1, 0, 0 }; 20 char mp[N][N]; 21 int Fire[N][N]; //火 22 bool vis[N][N]; 23 int x[N]; //火源的x 24 int y[N]; //火源的y 25 int l; //火源的个数 26 int Joe[N][N]; //Joe 27 int n, m; 28 int pi, pj; //Joe的坐标 29 30 struct node{ 31 int x, y, v; 32 }; 33 34 inline void init(){ 35 rep(i, 1, n) rep(j, 1, m){ 36 Joe[i][j] = 0; 37 Fire[i][j] = inf; 38 } 39 } 40 41 inline void input(){ 42 43 l = 0; 44 rep(i, 1, n) rep(j, 1, m){ 45 cin >> mp[i][j]; 46 47 //记录每个火源 48 if (mp[i][j] == 'J') pi = i, pj = j; 49 else if (mp[i][j] == 'F') x[l] = i, y[l++] = j; 50 } 51 } 52 53 inline bool check(int x, int y){ 54 return x >= 1 && x <= n && y >= 1 && y <= m; 55 } 56 57 void bfs_p(){ 58 59 queue<node> que; 60 Joe[pi][pj] = 1; 61 que.push(node{ pi, pj, 1 }); 62 63 while (!que.empty()){ 64 65 node tmp = que.front(); 66 que.pop(); 67 rep__(p, 0, 4){ 68 69 int dx = tmp.x + mv_x[p]; 70 int dy = tmp.y + mv_y[p]; 71 72 if (check(dx, dy) && !Joe[dx][dy] && mp[dx][dy] != '#'){ 73 Joe[dx][dy] = tmp.v + 1; 74 que.push(node{ dx, dy, tmp.v + 1 }); 75 } 76 } 77 } 78 } 79 80 void bfs_f(int fi, int fj){ 81 82 rep(i, 1, n) rep(j, 1, m) vis[i][j] = 0; 83 queue<node> que; 84 85 Fire[fi][fj] = 1; 86 vis[fi][fj] = true; 87 que.push(node{ fi, fj, 1 }); 88 89 while (!que.empty()){ 90 91 node tmp = que.front(); 92 que.pop(); 93 rep__(p, 0, 4){ 94 95 int dx = tmp.x + mv_x[p]; 96 int dy = tmp.y + mv_y[p]; 97 98 if (check(dx, dy) && !vis[dx][dy] && mp[dx][dy] != '#'){ 99 vis[dx][dy] = true; 100 101 if (tmp.v + 1 < Fire[dx][dy]) //比较与之前的火源,哪个最先烧到这个点 102 Fire[dx][dy] = tmp.v + 1, que.push(node{ dx, dy, tmp.v + 1 }); 103 104 // cout << "Fire[][] " << Fire[dx][dy] << endl; 105 106 } 107 } 108 } 109 110 111 } 112 113 void search_fire(){ 114 115 rep__(i, 0, l){ 116 bfs_f(x[i], y[i]); 117 } 118 } 119 120 void get_ans(){ 121 122 int ans = inf; 123 124 //先把Fire地图所有的inf,也就是无法到达的点赋值为0,方便比较 125 rep(i, 1, n) rep(j, 1, m) if (Fire[i][j] == inf) Fire[i][j] = 0; 126 127 //一种情况,Joe到达某点时间比Fire短, 128 //另一个情况,可能Fire到达不了那个点,于是Fire[x][y] == 0,所有有个特殊判断 Fire[x][y] == 0 129 130 //下面就是四个边界情况了 131 rep(i, 1, n){ 132 if (i == 1 || i == n){ 133 rep(j, 1, m){ 134 if (Joe[i][j] < Fire[i][j] || (Fire[i][j] == 0 && Joe[i][j] != 0)) 135 ans = min(ans, Joe[i][j]); 136 } 137 } 138 else { 139 if (Joe[i][1] < Fire[i][1] || (Fire[i][1] == 0 && Joe[i][1] != 0)) 140 ans = min(ans, Joe[i][1]); 141 142 if (Joe[i][m] < Fire[i][m] || (Fire[i][m] == 0 && Joe[i][m] != 0)) 143 ans = min(ans, Joe[i][m]); 144 } 145 } 146 147 if (ans == inf) cout << "IMPOSSIBLE" << endl; 148 else cout << ans << endl; 149 } 150 151 int main(){ 152 153 ios::sync_with_stdio(false); 154 cin.tie(0); 155 156 int T; 157 cin >> T; 158 159 rep(i, 1, T){ 160 161 cin >> n >> m; 162 init(); //初始化 163 input(); //输入 164 bfs_p(); //Joe的bfs 165 search_fire(); //所有火源的bfs 166 get_ans(); //得到答案 167 } 168 169 170 return 0; 171 }