1. 程式人生 > >UVA 11624 Fire! 【bfs】

UVA 11624 Fire! 【bfs】

Joe works in a maze. Unfortunately,portions of the maze have caught on fire, and the owner of the maze neglectedto create a fire escape plan. Help Joe escape the maze.

Given Joe's location in the maze and which squares of themaze are on fire, you must determine whether Joe can exit the maze before thefire 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 fourdirections from each square that is on fire. Joe may exit the maze from anysquare that borders the edge of the maze. Neither Joe nor the fire may enter asquare that is occupied by a wall.

Input Specification

The first line of input contains a single integer, thenumber of test cases to follow. The first line of each test case contains thetwo integers R and C, separated byspaces, with 1 <= R,C <= 1000. Thefollowing R lines of the test case each contain one row of themaze. Each of these lines contains exactly C

 characters, andeach of these characters is one of:

·  #, a wall

·  ., a passable square

·  J, Joe's initialposition in the maze, which is a passable square

·  F, a square that is onfire

There will be exactly one J in each test case.

Sample Input

2

4 4

####

#JF#

#..#

#..#

3 3

###

#J.

#.F

Output Specification

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

Output for SampleInput

3

IMPOSSIBLE

題意:

一個男人在迷宮裡工作,有一天,迷宮裡的幾塊地突然著火了,火勢在水平方向和豎直方向上蔓延。每一個單位時間蔓延一格。

這個男人想要逃出迷宮,他也只能向水平方向和豎直方向逃跑。每單位時間移動一格。‘#’代表牆壁,這個人無法穿過牆壁,火勢也無法蔓延到牆壁。問這個男人是否能逃離迷宮,如果能,輸出最少時間。如果不能,輸出impossible。

這題需要注意的是,起火點不唯一

我們先對所有起火點進行bfs,計算出火勢到達每一個格子所需要的時間。

然後在對這個人的起點進行bfs,如果這個人到達某個格子所需要的時間比火勢蔓延到該格子所需要的時間早。那麼這個人可以順利通過這個格子。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
using namespace std;
#define LL long long
#define M(a,b) memset(a,b,sizeof(a))
const int MAXN = 1e3+5;
const int INF =  0x3f3f3f3f;
int X[5] = {0,0,0,-1,1};
int Y[5] = {0,1,-1,0,0};
queue<pair<int,int> >q;
int vis1[MAXN][MAXN];
int vis2[MAXN][MAXN];
int MAP[MAXN][MAXN];
vector<pair<int,int> >v;///儲存所有著火點
int jx,jy;
int r,c;
void bfs1()///算出火勢蔓延到所有格子的時間
{
    for(int i=0; i<v.size(); i++)
    {
        q.push(make_pair(v[i].first,v[i].second));
        vis1[v[i].first][v[i].second] = 1;
    }

    while(!q.empty())
    {
        int x1 = q.front().first;
        int y1 = q.front().second;
        q.pop();
        for(int i=1; i<=4; i++)
        {
            int xx = x1 +X[i];
            int yy = y1 +Y[i];
            if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&vis1[xx][yy]==0&&MAP[xx][yy]!=-1)
            {
                vis1[xx][yy] = vis1[x1][y1]+1;
                q.push(make_pair(xx,yy));
            }
        }
    }
}
int bfs2(int x,int y)///計算出這個人到達所有格子的時間
{
    while(!q.empty()) q.pop();
    q.push(make_pair(x,y));
    vis2[x][y] = 1;
    while(!q.empty())
    {
        int x1 = q.front().first;
        int y1 = q.front().second;
        if((x1==1||x1==r||y1==1||y1==c))///到達邊界時,逃脫成功
        {
            return vis2[x1][y1];
        }
        q.pop();
        for(int i=1; i<=4; i++)
        {
            int xx = x1 +X[i];
            int yy = y1 +Y[i];
            if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&vis2[xx][yy]==0&&MAP[xx][yy]!=-1)
            {
                vis2[xx][yy] = vis2[x1][y1]+1;
                if(vis2[xx][yy]>=vis1[xx][yy]&&vis1[xx][yy]!=0) ///人到達該格子的時間要早於火到達的,且是火能到達的。
                    continue;
                q.push(make_pair(xx,yy));
            }
        }
    }
    return -1;
}
void init()
{
    M(vis2,0);
    M(vis1,0);
    v.clear();
    while(!q.empty()) q.pop();
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        init();
        scanf("%d %d",&r,&c);
        for(int i=1; i<=r; i++)
        {
            for(int j=1; j<=c; j++)
            {
                char temp;
                cin>>temp;
                if(temp=='#') MAP[i][j] = -1;
                if(temp=='.') MAP[i][j] = 1;
                if(temp=='F')
                {
                    v.push_back(make_pair(i,j));///著火點不唯一
                }
                if(temp=='J')
                {
                    jx = i;
                    jy = j;
                }
            }
        }
        bfs1();
        int ans = bfs2(jx,jy);
        if(ans==-1)
        {
            printf("IMPOSSIBLE\n");
        }
        else
        {
            printf("%d\n",ans);
        }
    }
    return 0;
}
//2
//3 4
//F#..
//#J..
//....