UVA11624 Fire!(兩次bfs,第一次預處理)
阿新 • • 發佈:2018-11-26
題意翻譯
大火蔓延的迷宮
題目大意 你的任務是幫助Joe走出一個大火蔓延的迷宮。Joe每分鐘可以走到上下左右4個方向的相鄰格子之一,而所有著火的格子都會四周蔓延(即如果某個空格子與著火格子有公共邊,則下一分鐘這個空格子將著火)。迷宮中有一些障礙格,Joe和火都無法進入。當Joe走到一個迷宮的邊界格子時,我們認為他已經出了迷宮。
輸入資料 第一行為資料組數T。每一組測試資料格式如下: 第一行為兩個整數R和C(1<=R,C<=1000)。以下R行每行有C個字元,即迷宮,其中“#”表示牆和障礙物,“.”表示空地,“J”是joe的初始位置(也就是空地),”F”是著火格子。每組資料的迷宮中恰好有一個格是”J”。
輸出資料 對於每組測試資料,如無法走出迷宮,則輸出IMPOSSIBLE,否則輸出走出迷宮的最短時間(單位:分鐘)。
感謝@hicc0305 提供的翻譯
輸入輸出樣例
輸入樣例#1: 複製
2 4 4 #### #JF# #..# #..# 3 3 ### #J. #.F
思路:首先,這個題目如果著火點不會傳染,那麼這個題就是一個類似於最短迷宮的題目,
現在著火點傳染,那麼我們可以先將某時間內這點的著火情況表示出來,也就是第一個bfs的作用,
後面的第二個bfs就往常一樣了。。。
程式碼:
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<stack> #define inf 0x3f3f3f3f #define maxn 1050 using namespace std; struct node { int x,y,t; node(int x,int y,int t):x(x),y(y),t(t) {} }; queue<node>q; int t,n,m,p[maxn][maxn],vis[maxn][maxn],sx,sy; int dx[]= {0,0,1,-1}; int dy[]= {1,-1,0,0}; char a[maxn][maxn]; void init_bfs() //預處理時間和著火點 { while(!q.empty()) { node u=q.front(); q.pop(); for(int i=0; i<4; i++) { int vx=u.x+dx[i],vy=u.y+dy[i]; if((vx>=1&&vx<=n&&vy>=1&&vy<=m)&&a[vx][vy]!='#'&&p[vx][vy]==inf) { q.push(node(vx,vy,0)); p[vx][vy]=p[u.x][u.y]+1; } } } } void bfs() { while(!q.empty()) q.pop(); q.push(node(sx,sy,0)); vis[sx][sy]=1; while(!q.empty()) { node u=q.front(); q.pop(); if(u.x==n||u.x==1||u.y==1||u.y==m) { printf("%d\n",u.t+1); return; } for(int i=0; i<4; i++) { int vx=u.x+dx[i],vy=u.y+dy[i]; if((vx>=1&&vx<=n&&vy>=1&&vy<=m)&&a[vx][vy]!='#'&&!vis[vx][vy]&&(u.t+1<p[vx][vy])) { q.push(node(vx,vy,u.t+1)); vis[vx][vy]=1; } } } puts("IMPOSSIBLE"); return; } int main() { scanf("%d",&t); while(t--) { while(!q.empty()) q.pop(); memset(vis,0,sizeof(vis)); memset(p,inf,sizeof(p)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%s",a[i]+1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(a[i][j]=='J') sx=i,sy=j; if(a[i][j]=='F') { q.push(node(i,j,0)); p[i][j]=0; } } init_bfs(); bfs(); } return 0; }