J - Fire! (bfs)
阿新 • • 發佈:2018-12-25
對火的蔓延和joe走的情況分別進行bfs,這裡注意記錄火蔓延的方法:
vFire[q.x][q.y] = vFire[s.x][s.y] + 1; 表示標記該位置是經過多長時間燒過來的(由上一個位置+1得到) 判斷某位置是否可走,則只需看Joe走到該位置的時間是否小於火走過來的時間即可
還有就是地圖上可能不止一個火種也可能沒有火種,需要開一個數組記錄一下#include<queue> #include<stdio.h> #include<string.h> using namespace std; #define maxn 1005 #define inf 0xfffffff struct node{ int x; int y; }; node JoeSite, FireSite[maxn*maxn];//因為火可能不止一處,所以開一個數組儲存所有的火焰的位置 char G[maxn][maxn]; int vJoe[maxn][maxn], vFire[maxn][maxn];//分別記錄joe經過多久走到該位置,fire經過多久燒過來 int dir[4][2] = { {0,1},{0,-1},{1,0},{-1,0} }; int M, N, nFire; void BfsFire() { node s, q; queue<node> Q; int i; for(i=0; i<nFire; i++) { Q.push(FireSite[i]); vFire[ FireSite[i].x ][ FireSite[i].y ] = 1; } while(Q.size()) { s = Q.front(); Q.pop(); for(i=0; i<4; i++) { q = s; q.x += dir[i][0]; q.y += dir[i][1]; if(q.x>=0&&q.x<M && q.y>=0&&q.y<N && G[q.x][q.y]!='#' && vFire[q.x][q.y]==inf) { vFire[q.x][q.y] = vFire[s.x][s.y] + 1; // 標記該位置是經過多長時間燒過來的(由上一個位置+1得到) Q.push(q); } } } } int IsBorder(int x, int y)//判斷是否是邊界並且是否比火焰先到達 { if( (x==0 || x==M-1 || y==0 || y==N-1) && vJoe[x][y] < vFire[x][y] ) return 1; return 0; } int BfsJoe() { queue<node> Q; node s, q; int i; vJoe[JoeSite.x][JoeSite.y] = 1; Q.push(JoeSite); while(Q.size()) { s = Q.front();Q.pop(); if(IsBorder(s.x, s.y) == 1) return vJoe[s.x][s.y]; for(i=0; i<4; i++) { q = s;//這一步不能忘呀,每一次迴圈q的初始態都是一樣的 ,即都是s q.x += dir[i][0]; q.y += dir[i][1]; if(q.x>=0&&q.x<M && q.y>=0&&q.y<N && G[q.x][q.y]!='#' && vJoe[q.x][q.y]==0) { vJoe[q.x][q.y] = vJoe[s.x][s.y] + 1; Q.push(q); } } } return -1; } int main() { int T; scanf("%d", &T); while(T--) { int i, j, ans; scanf("%d%d", &M, &N); nFire = 0; for(i=0; i<M; i++) { scanf("%s", G[i]); for(j=0; j<N; j++) { vJoe[i][j] = 0; vFire[i][j] = inf; if(G[i][j] == 'J') JoeSite.x = i, JoeSite.y = j; if(G[i][j] == 'F')//火不止一處,分別記錄 { FireSite[nFire].x = i; FireSite[nFire++].y = j; } } } BfsFire(); ans = BfsJoe(); if(ans == -1) printf("IMPOSSIBLE\n"); else printf("%d\n", ans); } return 0; }