【UVA 11624】Fire!(BFS)

Description

Joe works in a maze. Unfortunately, portions of the maze have
caught on fire, and the owner of the maze neglected to create a fire
escape plan. Help Joe escape the maze.
Given Joe’s location in the maze and which squares of the maze
are on fire, you must determine whether Joe can exit the maze before
the fire reaches him, and how fast he can do it.
Joe and the fire each move one square per minute, vertically or
horizontally (not diagonally). The fire spreads all four directions
from each square that is on fire. Joe may exit the maze from any
square that borders the edge of the maze. Neither Joe nor the fire
may enter a square that is occupied by a wall.

Input

The first line of input contains a single integer, the number of test
cases to follow. The first line of each test case contains the two
integers R and C, separated by spaces, with 1 ≤ R, C ≤ 1000. The
following R lines of the test case each contain one row of the maze. Each of these lines contains exactly
C characters, and each of these characters is one of:
• #, a wall
• ., a passable square
• J, Joe’s initial position in the maze, which is a passable square
• F, a square that is on fire
There will be exactly one J in each test case.

Output

For each test case, output a single line containing ‘IMPOSSIBLE’ if Joe cannot exit the maze before the
fire reaches him, or an integer giving the earliest time Joe can safely exit the maze, in minutes.

Sample Input

2
4 4
####
#JF#
#..#
#..#
3 3
###
#J.
#.F

Sample Output

3
IMPOSSIBLE

题目大意

有一个迷宫,‘#’表示围墙,‘J’表示john,‘F’表示火,火在每个时间单位会向上下左右蔓延,问你John能否逃出这个迷宫,如果可以最小的时间花费是多少,如果不行,输出IMPOSSIBLE。John逃出这个迷宫的条件是他到达地图边界之后走出这个边界,注意有火的地方John是没法走的。

思路

WA了15发,都快怀疑人生了。思路比较清晰,对John和火都进行BFS,但是有先后顺序,必须是先对火进行BFS在对John,这样可以保证John不会走到有火的地方去。注意一种特殊的情况,就是John一开始就已经在迷宫的边界,这时要对这种情况做特殊的处理,我就是因为这个WA了15次!

还有一个非常需要注意的地方就是一开始不一定只有一个地方着火,有可能有多个,所以开始状态要把所有着火的点都入队列。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;
const int maxn=1000+5;

int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
char map[maxn][maxn];
int n,m,vis[maxn][maxn];
int stax,stay,fstax,fstay;

struct proc
{
    int x,y,step;
    char id;//判断是John还是火Fire
};

vector<proc> v;//用来记录所有一开始着火的点

int bfs(proc vw)
{
    memset(vis,0,sizeof(vis));
    queue<proc> q;
    proc vn;
    vw.step=0;
    for(int i=0;i<v.size();i++)
    {
        if(v[i].id=='F') q.push(v[i]);//将一开始所有
着火的点入队列     
        //cout<<v[i].x<<" "<<v[i].y<<" "<<v[i].id<<endl;
    }
    q.push(vw);
    //int k=1;
    while(!q.empty())
    {
        vw=q.front();
        q.pop();
        if(vw.id=='J'&&(vw.x==n||vw.x==1||vw.y==m||vw.y==1))//一开始就处于边界的情况必须在这里进行特殊的处理。
        {
            return vw.step+1;
        }
        //cout<<vw.x<<" "<<vw.y<<" "<<vw.id<<" "<<k++<<endl;
        if(vw.id=='F')
        {
            for(int i=0;i<4;i++)
            {
                vn.x=vw.x+dir[i][0];
                vn.y=vw.y+dir[i][1];
                if(vn.x<=0||vn.x>n||vn.y<=0||vn.y>m||map[vn.x][vn.y]=='#'||map[vn.x][vn.y]=='F')
                    continue;
                map[vn.x][vn.y]='F';
                vn.step=vw.step+1;
                vn.id='F';
                q.push(vn);
            }
        }
        else
        {
            for(int i=0;i<4;i++)
            {
                vn.x=vw.x+dir[i][0];
                vn.y=vw.y+dir[i][1];
                if(vis[vn.x][vn.y]||map[vn.x][vn.y]=='#'||map[vn.x][vn.y]=='F')
                    continue;
                if(vn.x>=n+1||vn.x<1||vn.y>=m+1||vn.y<1)//判断是否已经走到了边界,注意这里无法处理John一开始就在边界的情况,因为这时他已经走了一步了。
                {
                    return vw.step+1;
                }
                vis[vn.x][vn.y]=1;
                vn.id='J';
                vn.step=vw.step+1;
                q.push(vn);
            }
        }
    }
    return -1;
}

int main()
{
    int t;
    int cas;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        v.clear();
        proc john,fire;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            getchar();//注意吸收回车符。最妥当的方法是用cin而不用scanf。如果用cin的话最好从0开始存,存取时按行存取,如:cin>>map[i]。表示读第i行。但是cin的时间花费比较高,数据大容易TLE
            for(int j=1;j<=m;j++)
            {
                scanf("%c",&map[i][j]);
                if(map[i][j]=='#') vis[i][j]=1;
                if(map[i][j]=='J') 
                {
                    john.id='J';
                    john.x=i;
                    john.y=j;
                    john.step=0;
                }
                if(map[i][j]=='F')
                {
                    v.push_back((proc){i,j,0,'F'});
                }
            }
        }
        int ans=bfs(john);
        if(ans==-1) printf("IMPOSSIBLE\n");
        else printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/iceiceicpc/article/details/52097519
今日推荐