链接:点击打开链接
Description
The Barareh village is on fire due to the attack of the virtual enemy. Several places are already on fire and the fire is spreading fast to other places. Khorzookhan who is the only person remaining alive in the war with the virtual enemy, tries to rescue himself by reaching to the only helicopter in the Barareh villiage. Suppose the Barareh village is represented by an n × m grid. At the initial time, some grid cells are on fire. If a cell catches fire at time x, all its 8 vertex-neighboring cells will catch fire at time x + k. If a cell catches fire, it will be on fire forever. At the initial time, Khorzookhan stands at cell s and the helicopter is located at cell t. At any time x, Khorzookhan can move from its current cell to one of four edge-neighboring cells, located at the left, right, top, or bottom of its current cell if that cell is not on fire at time x + 1. Note that each move takes one second. Your task is to write a program to find the shortest path from s to t avoiding fire.
Input
There are multiple test cases in the input. The first line of each test case contains three positive integers n, m and k (1 ⩽ n,m,k ⩽ 100), where n and m indicate the size of the test case grid n × m, and k denotes the growth rate of fire. The next n lines, each contains a string of length m, where the jth character of the ith line represents the cell (i, j) of the grid. Cells which are on fire at time 0, are presented by character “f”. There may exist no “f” in the test case. The helicopter and Khorzookhan are located at cells presented by “t” and “s”, respectively. Other cells are filled by “-” characters. The input terminates with a line containing “0 0 0” which should not be processed.
Output
For each test case, output a line containing the shortest time to reach t from s avoiding fire. If it is impossible to reach t from s, write “Impossible” in the output.
Sample Input
7 7 2
f------
-f---f-
----f--
-------
------f
---s---
t----f-
3 4 1
t--f
--s-
----
2 2 1
st
f-
2 2 2
st
f-
0 0 0
Sample Output
4
Impossible
Impossible
1
题意:一个n*m的表格,从s点到t点,这个格子里有的地方有火,并且火会每隔k个时间向周围的八个格子蔓延,火一烧起来就不会灭,活结点(人)能够向上下左右四个方向走。如果能够走到终点就输出所走的步数,不能的话就输出Impossible.
思路:两个BFS,对于活结点人和火分别bfs,如果人(活结点)遍历到t节点,则说明到达终点,输出遍历的层数;如果火遍历到t节点,则说明到达不了,直接输出Impossible
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
struct Node{
int x; //x坐标
int y; //y坐标
};
struct Node num,endnum,temp; //endnum为最终节点,其他两个临时变量
queue<struct Node> que,quefire; //que为节点bfs产生,quefire为火bfs产生
int label[1005][1005]; //记录节点是否遍历,为1时que遍历,为2时火遍历
int yes = 0; //是否能够抵达最终节点
void bfsf(){ //对火进行遍历
num = quefire.front(); //取出第一个节点
quefire.pop(); //删除第一个节点
if(num.x == -1){ //为-1则说明遍历到结束
return;
}
while(num.x != -1){ //为1则说明该轮遍历结束
//printf("#fire:%d %d\n", num.x,num.y );
for(int i=-1;i<=1;i++){ //总共有九种情况
for(int j=-1;j<=1;j++){
if(label[num.x+i][num.y+j] != 2){ //如果这个点没有火,就点火
temp.x = num.x+i;
temp.y = num.y+j;
if(temp.x == endnum.x && temp.y == endnum.y){ //把终点点燃啦,不可能到终点
yes = -1;
}
quefire.push(temp);
//printf("push fire :%d %d %d\n", temp.x,temp.y,label[temp.x][temp.y]);
label[temp.x][temp.y] = 2;
}
}
}
num = quefire.front(); //取出该轮的下一个节点
quefire.pop();
}
temp.x = -1; //最后加一个-1来作为该轮的终点
temp.y = -1;
quefire.push(temp);
}
void bfs(){ //对节点逐步遍历,基本同上
num = que.front();
que.pop();
if(num.x == -1){
return;
}
while(num.x != -1){
for(int i=-1;i<=1;i++){ //不同于上面的,这里只有四个方向
for(int j=-1;j<=1;j++){
if(abs(i) == abs(j));
else if(0 == label[num.x+i][num.y+j]){ //只有是0才要遍历
temp.x = num.x+i;
temp.y = num.y+j;
if(temp.x == endnum.x && temp.y == endnum.y){
yes = 1;
// printf("end:%d %d\n", temp.x,temp.y);
}
que.push(temp);
label[temp.x][temp.y] = 1;
}
}
}
num = que.front();
que.pop();
}
temp.x = -1;
temp.y = -1;
que.push(temp);
}
int main(){
//freopen("1.txt", "r", stdin);
int n, m, k;
char ch;
while(~scanf("%d%d%d", &n,&m,&k)){
if(n==0 && m==0 && k==0){
break;
}
//初始化
memset(label,0,sizeof(label));
yes=0;
while(!que.empty())que.pop();
while(!quefire.empty())quefire.pop();
//四周都设为有火但是不能继续遍历
for(int i=0;i<=n+1;i++){
label[i][0] =2;
label[i][m+1] = 2;
}
for(int i=0;i<=m+1;i++){
label[0][i] =2;
label[n+1][i] = 2;
}
//将每个有火的点和起始终点全部处理
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf(" %c", &ch);
num.x = i;
num.y = j;
if(ch == 'f'){
quefire.push(num);
label[num.x][num.y] = 2;
}
else if(ch == 's'){
que.push(num);
}
else if(ch == 't'){
endnum.x = i;
endnum.y = j;
}
}
}
//-1作为终点
num.x = -1;
num.y = -1;
que.push(num);
quefire.push(num);
int ans = 0; //答案就是一次次的遍历数
while(1){
ans++;
if(ans % k == 0){
if(!quefire.empty()){
bfsf();
}
//else { //开始觉得队列为空是全部都是火
// printf("Impossible1\n"); //后来才发现原来是可以没有火的
// break;
//}
}
if(!que.empty()){ //遍历还可以继续
bfs();
}
else { //不能继续了
printf("Impossible\n");
break;
}
if(yes == 1){ //是可以到达终点的
printf("%d\n", ans);
break;
}
if(yes == -1){ //已经确定是不能到达终点的
printf("Impossible\n");
break;
}
}
}
}