题目链接:https://vjudge.net/problem/UVA-11624
题解:
坑点:“portions of the maze havecaught on fire”, 表明了起火点不唯一。
火和人使用同一种结构体,用id来区别类型。BFS求解:首先将所有火苗入队,然后人再入队(肯定要火苗先入队,因为人要根据火当前烧到哪里来进行移动)。
对于一个尝试点:如果当前的id是人,且走出界,则逃生成功。如果没有走出界,则:
写法一(模拟过程): 如果没有走出界:如果id是火,且此地方是通道,则不管有没有vis过,都把它烧了,即把地图改为‘F’;如果id是人,且此地方是通道且没有被vis过,则进去。
写法二:其实火苗的本质作用是什么?就是禁止人vis那个地方,相当于会扩散的墙。有一点需要注意:对于一个通道,如果人比火先访问,那么其他相邻的通道,都是人先访问的(BFS的特点),所以火在扩散的时候,不用把周围也改为‘F’,直接把它标为vis,对于vis过的点,火和人都 不能再访问。那么我们就不用把火和人分开来处理了:对于一个合法的尝试点,如果此点是通道,则把它标为已经vis,之后入队即可。
写法一:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 #define ms(a,b) memset((a),(b),sizeof((a))) 13 using namespace std; 14 typedef long long LL; 15 const int INF = 2e9; 16 const LL LNF = 9e18; 17 const int MOD = 1e9+7; 18 const int MAXN = 1e3+10; 19 20 int n, m; 21 char g[MAXN][MAXN]; 22 int vis[MAXN][MAXN], dir[4][2] = {1,0,0,1,-1,0,0,-1}; 23 24 struct node 25 { 26 int x, y, id, step; //id为是人是火的标签 27 }; 28 29 queue<node>que; 30 int bfs() 31 { 32 ms(vis, 0); 33 while(!que.empty()) que.pop(); 34 35 node now, tmp; 36 for(int i = 1; i<=n; i++) //先将所有的火一次性放进队列中 37 for(int j = 1; j<=m; j++) 38 { 39 if(g[i][j]=='F') 40 { 41 now.x = i; now.y = j; 42 now.step = 0; now.id = 0; 43 vis[now.x][now.y] = 1; 44 que.push(now); 45 } 46 } 47 48 for(int i = 1; i<=n; i++) //将人放进队列中 49 for(int j = 1; j<=m; j++) 50 { 51 if(g[i][j]=='J') 52 { 53 now.x = i; now.y = j; 54 now.step = 0; now.id = 1; 55 vis[now.x][now.y] = 1; 56 que.push(now); 57 } 58 } 59 60 while(!que.empty()) 61 { 62 now = que.front(); 63 que.pop(); 64 65 for(int i = 0; i<4; i++) 66 { 67 tmp.x = now.x + dir[i][0]; 68 tmp.y = now.y + dir[i][1]; 69 tmp.step = now.step + 1; 70 tmp.id = now.id; 71 if(tmp.id==1 && (tmp.x<1 || tmp.x>n || tmp.y<1 || tmp.y>m) ) //如果是人,且走出界,则逃生成功 72 return tmp.step; 73 74 if(tmp.x>=1 && tmp.x<=n && tmp.y>=1 && tmp.y<=m) //位置合法 75 { 76 //如果是火,并且可以燃烧,不过他有没有vis过,都把它给烧了 77 if(tmp.id==0 && g[tmp.x][tmp.y]=='.' || g[tmp.x][tmp.y]=='J' ) 78 { 79 g[tmp.x][tmp.y] = 'F'; //这个地方变成火了 80 que.push(tmp); 81 } 82 //如果是人,并且这个地方是通道可没有vis过,则可行 83 if(tmp.id==1 && g[tmp.x][tmp.y]=='.' && !vis[tmp.x][tmp.y]) 84 { 85 vis[tmp.x][tmp.y] = 1; 86 que.push(tmp); 87 } 88 } 89 } 90 } 91 return -1; 92 } 93 94 int main() 95 { 96 int T; 97 scanf("%d",&T); 98 while(T--) 99 { 100 scanf("%d%d", &n, &m); 101 for(int i = 1; i<=n; i++) 102 scanf("%s", g[i]+1); 103 104 int ans = bfs(); 105 if(ans==-1) 106 puts("IMPOSSIBLE"); 107 else 108 printf("%d ", ans); 109 } 110 }
写法二:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 #define ms(a,b) memset((a),(b),sizeof((a))) 13 using namespace std; 14 typedef long long LL; 15 const int INF = 2e9; 16 const LL LNF = 9e18; 17 const int MOD = 1e9+7; 18 const int MAXN = 1e3+10; 19 20 int n, m; 21 char g[MAXN][MAXN]; 22 int vis[MAXN][MAXN], dir[4][2] = {1,0,0,1,-1,0,0,-1}; 23 24 struct node 25 { 26 int x, y, id, step; 27 }; 28 29 queue<node>que; 30 31 int bfs() 32 { 33 ms(vis, 0); 34 while(!que.empty()) que.pop(); 35 36 node now, tmp; 37 for(int i = 1; i<=n; i++) 38 for(int j = 1; j<=m; j++) 39 { 40 if(g[i][j]=='F') 41 { 42 now.x = i; now.y = j; 43 now.step = 0; now.id = 0; 44 vis[now.x][now.y] = 1; 45 que.push(now); 46 } 47 } 48 49 for(int i = 1; i<=n; i++) 50 for(int j = 1; j<=m; j++) 51 { 52 if(g[i][j]=='J') 53 { 54 now.x = i; now.y = j; 55 now.step = 0; now.id = 1; 56 vis[now.x][now.y] = 1; 57 que.push(now); 58 } 59 } 60 61 while(!que.empty()) 62 { 63 now = que.front(); 64 que.pop(); 65 66 for(int i = 0; i<4; i++) 67 { 68 tmp.x = now.x + dir[i][0]; 69 tmp.y = now.y + dir[i][1]; 70 tmp.step = now.step + 1; 71 tmp.id = now.id; 72 if(tmp.id==1 && (tmp.x<1 || tmp.x>n || tmp.y<1 || tmp.y>m) ) //逃生成功 73 return tmp.step; 74 75 if(tmp.x>=1 && tmp.x<=n && tmp.y>=1 && tmp.y<=m 76 && !vis[tmp.x][tmp.y] && g[tmp.x][tmp.y]=='.' ) //如果此地方是通道且没有被vis,则把它标为vis 77 { 78 vis[tmp.x][tmp.y] = 1; 79 que.push(tmp); 80 } 81 } 82 } 83 return -1; 84 } 85 86 87 int main() 88 { 89 int T; 90 scanf("%d",&T); 91 while(T--) 92 { 93 scanf("%d%d", &n, &m); 94 for(int i = 1; i<=n; i++) 95 scanf("%s", g[i]+1); 96 97 int ans = bfs(); 98 if(ans==-1) 99 puts("IMPOSSIBLE"); 100 else 101 printf("%d ", ans); 102 } 103 }