1101-著火的房間(中等多源BFS問題)
阿新 • • 發佈:2021-01-27
技術標籤:刷題
題目描述
救救PIPI!!PIPI被關在一個著火的房間裡了!
該房間中有 nxm 個位置, 用一個字元矩陣表示。
‘s’ 代表PIPI的起點位置。
‘t’ 代表出口位置。
‘f’ 代表房間的著火點。
‘-’ 代表房間還未著火的點。
房間裡面有若干個著火點,每個著火點的移動速率是k , 意思是若一個位置在 x 時刻起火了,那麼在 x+k 時刻它周圍8個方向都會起火。
PIPI每秒能夠移動到上下左右四個方向中的一個未著火的位置。
請你程式設計計算可憐的PIPI能否成功逃離這個房間,如果PIPI能夠成功逃離這個房間,輸出PIPI逃出房間的最短時間,如果PIPI不能逃出這個房間,輸出"Impossible"。
輸入包含多組測試用例。
對於每一組測試用例,輸入第一行包含三個整數 n,m,k .分別代表房間位置的行數,列數,以及著火點的移動速率。(1<=n,m,k<=100)
接下來輸入一個n*m的字元矩陣,代表房間在0時刻的狀態。
以0 0 0 代表輸入結束。
輸出
對於每組樣例,輸出一行。如果PIPI能夠成功逃離這個房間,輸出PIPI逃出房間的最短時間,如果PIPI不能逃出這個房間,輸出"Impossible"。
樣例輸入
樣例輸出
4
Impossible
Impossible
1
題解程式碼如下:
#include<bits/stdc++.h>
using namespace std;
int n,m,k,sx,sy,fx,fy;
const int N=105;
const int INF=1e9;
char maze[N][N];
int vis[N][N];
int dir[8][2]={0,1,0,-1,1,0,-1,0,-1,1,1,-1,1,1,-1,-1};
int fireTime[N][N]; ///記錄可著火點的著火時間
struct Node{
int x,y,t; ///表示到(x,y)點時所用的時間為t
};
bool judge(int x,int y){
if(x<0||x>= n||y<0||y>=m) return false;
return true;
}
void getFiretime(){
//memset(fireTime,-1,sizeof fireTime);
queue<Node> q;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(maze[i][j]=='f') fireTime[i][j]=0,q.push({i,j,0});
else fireTime[i][j]=INF;
if(maze[i][j]=='s') sx=i,sy=j;
if(maze[i][j]=='t') fx=i,fy=j;
}
}
while(q.size()){
Node now = q.front();q.pop();
for(int i=0;i<8;i++){
int xx=now.x+dir[i][0],yy=now.y+dir[i][1];
if(judge(xx,yy)&&fireTime[xx][yy]==INF){
q.push({xx,yy,now.t+k});
fireTime[xx][yy]=now.t+k;
}
}
}
}
void bfs(){
queue<Node> q;
memset(vis,0,sizeof vis);
q.push({sx,sy,0});
vis[sx][sy]=1;
while(q.size()){
Node now = q.front();q.pop();
if(now.x==fx&&now.y==fy){
printf("%d\n",now.t);
return;
}
for(int i=0;i<4;i++){
int xx=now.x+dir[i][0],yy=now.y+dir[i][1];
if(judge(xx,yy)&&vis[xx][yy]==0&&now.t+1<fireTime[xx][yy]){
q.push({xx,yy,now.t+1});
vis[xx][yy]=1;
}
}
}
printf("Impossible\n");
}
int main(){
while(~scanf("%d%d%d",&n,&m,&k)&&n+m+k){
for(int i=0;i<n;i++) scanf("%s",maze[i]);
getFiretime(); ///將著火點預處理
bfs();
}
return 0;
}