UVA 11624 Fire! 【广搜】

J - Fire!  UVA

题目描述

乔在迷宫中工作。不幸的是,迷宫的一部分着火了,迷宫的主人没有制定火灾的逃跑计划。请帮助乔逃离迷宫。根据乔在迷宫中的位置以及迷宫的哪个方块着火,你必须确定火焰烧到他之前,乔是否可以离开迷宫,如果能离开他能跑多快。
乔和火每分钟移动一个方格,上、下、左、右,四个方向中的一个。火势向四个方向同时蔓延。乔可以从迷宫的任何一个边界逃离迷宫。无论是乔还是火都不会到达有墙的位置。

输入

第一行输入包含一个整数,即测试次数
每个测试用例的第一行包含两个
整数R和C,用空格分隔,1≤R,C≤1000
下面R行中,每一行都包含C个字符,以及每个字符是以下之一:
# 代表墙
. 代表空地,火和乔是可通行的
J 乔在迷宫中最初的位置,火和乔是可通行的
F 代表火
在每组测试中只有一个J

输出

对于每个测试用例,如果在火蔓延的时候烧到了乔,则乔无法逃出迷宫,输出'IMPOSSIBLE'如果乔能逃出迷宫,则输出乔最快可以在几分钟内安全逃出迷宫,每组输出占一行

样例输入

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

样例输出

3
IMPOSSIBLE

思路:两次bfs,第一个bfs求出火蔓延到每个地方所需的最小时间。第二个bfs求Joe在火烧的同时(到达某一位置时火烧到的时间一定要比其大)是否可以到达边界·,以及逃出迷宫的时间。

注意:起火点不只一个。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1005;
int vis[maxn][maxn];
int vis2[maxn][maxn];
char e[maxn][maxn];
int R,C;
int X[5]= {0,1,-1,0,0};
int Y[5]= {0,0,0,1,-1};
struct node
{
    int x;
    int y;
};
queue<node>q;
void firebfs()
{
    for(int i=1; i<=R; i++)
        for(int j=1; j<=C; j++)
        {
            if(e[i][j]=='F')///找到每一个起火点,并且将其入队列
            {
                vis[i][j]=0;
                node p;
                p.x=i;
                p.y=j;
                q.push(p);
            }

        }
    while(!q.empty())
    {
        node head=q.front();
        q.pop();
        for(int i=1; i<5; i++)
        {
            int xx=head.x+X[i];
            int yy=head.y+Y[i];
            if(xx>=1&&xx<=R&&yy>=1&&yy<=C&&vis[xx][yy]==-1&&e[xx][yy]!='#')///范围以及可走的条件
            {
                vis[xx][yy]=vis[head.x][head.y]+1;///vis数组表示到达每一个点所需最短时间
                node tmp;
                tmp.x=xx;
                tmp.y=yy;
                q.push(tmp);
            }
        }

    }
}
int joebfs(int x,int y)
{
    while(!q.empty())
        q.pop();
    vis2[x][y]=0;
    node p;
    p.x=x;
    p.y=y;
    q.push(p);
    while(!q.empty())
    {
        node head=q.front();
        q.pop();
        if(head.x==1||head.y==1||head.x==R||head.y==C) ///到达边界时,逃脱成功
            return vis2[head.x][head.y]+1; ///从边界逃离需要+1分钟
        for(int i=1; i<5; i++)
        {
            int xx=head.x+X[i];
            int yy=head.y+Y[i];
            if(xx>=1&&xx<=R&&yy>=1&&yy<=C&&vis2[xx][yy]==-1&&e[xx][yy]!='#')
            {
                vis2[xx][yy]=vis2[head.x][head.y]+1;
                if(vis2[xx][yy]>=vis[xx][yy]&&vis[xx][yy]!=-1)///人到达该点的时间要晚于火到达的,且是火能到达的。
                    continue;
                node tmp;
                tmp.x=xx;
                tmp.y=yy;
                q.push(tmp);
            }
        }
    }
    return -1;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&R,&C);
        int jx,jy,fx,fy;
        memset(vis,-1,sizeof(vis));
        memset(vis2,-1,sizeof(vis2));
        while(!q.empty())
            q.pop();

        for(int i=1; i<=R; i++)
            for(int j=1; j<=C; j++)
                cin>>e[i][j];
        for(int i=1; i<=R; i++)
            for(int j=1; j<=C; j++)
            {
                if(e[i][j]=='J')
                {
                    jx=i;
                    jy=j;
                }
            }
        firebfs();
        int ans=joebfs(jx,jy);
        if(ans==-1)
            printf("IMPOSSIBLE\n");
        else
            printf("%d\n",ans);
    }
    return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值