【UVA11624】Fire!

题面

  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.

题意

  在一个 nm 的网格图中,有以下几种类型的点:
  ①.‘#’,表示该网格不可以通过
  ②.‘.’,表示该网格可以通过
  ③.‘J’,表示J的起点
  ④.‘F’,表示F的起点,F可能有多个起点
  JF每单位时间能够移动一格,当J到达网格边缘时可以在移动一次来脱离网格,F在不停地追赶J,请问J脱离网格至少要多少步?(可以认为F有无限个,即当前任意一个F所在格子的四联通块在下一单位时间内都可以有一个F

解法

bfs 求最短路:
  首先从F的每一个起点出发,设 gij 表示F到达 ij 的最短时间,如果该格子为‘#’,那么 g 值为-1
  求解完g值之后,从J的起点出发,设 disij 表示J到达该点的最短时间,如果该格子为‘#’,那么 dis 值为-1
  很容易看出,只有满足 disijgij 时,J才能够安全通过,所以判断一次即可

复杂度

O( Tnk ), k <script type="math/tex" id="MathJax-Element-11">k</script>为常数

代码

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<queue>
#define Lint long long int
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1010;
struct node
{
    int x,y;
};
int dis[MAXN][MAXN];
int g[MAXN][MAXN];
int T,n,m;
queue<node> q;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
void Prepare(int x,int y)
{
    node tmp;
    int tx,ty;
    g[x][y]=0;
    q.push( (node){ x,y } );
    while( !q.empty() )
    {
        tmp=q.front(),q.pop();
        for(int k=1;k<=4;k++)
        {
            tx=tmp.x+dx[k],ty=tmp.y+dy[k];
            if( tx<1 || tx>n || ty<1 || ty>m || g[tx][ty]==-1 )   continue ;
            if( g[tx][ty]>g[tmp.x][tmp.y]+1 )
            {
                g[tx][ty]=g[tmp.x][tmp.y]+1;
                q.push( (node){ tx,ty } );
            }
        }
    }
}
void bfs(int x,int y)
{
    node tmp;
    int tx,ty;
    for(int i=1;i<=n;i++)   for(int j=1;j<=m;j++)   dis[i][j]=INF;
    dis[x][y]=0,q.push( (node){ x,y } );
    while( !q.empty() )
    {
        tmp=q.front(),q.pop();
        for(int k=1;k<=4;k++)
        {
            tx=tmp.x+dx[k],ty=tmp.y+dy[k];
            if( tx<1 || tx>n || ty<1 || ty>m || g[tx][ty]==-1 )   continue ;
            if( dis[tmp.x][tmp.y]+1>=g[tx][ty] || dis[tmp.x][tmp.y]+1>=dis[tx][ty] )   continue ;
            dis[tx][ty]=dis[tmp.x][tmp.y]+1;
            q.push( (node){ tx,ty } );
        }
    }
}
int main()
{
    int sx,sy,cnt,ans;
    string s;
    scanf("%d",&T);
    node p[MAXN*10];
    while( T-- )
    {
        scanf("%d%d",&n,&m);
        ans=INF;
        sx=sy=cnt=0;
        memset( g,INF,sizeof g );
        for(int i=1;i<=n;i++)
        {
            cin>>s;
            for(int j=0;j<=m-1;j++)
                if( s[j]=='J' )   sx=i,sy=j+1,g[i][j+1]=INF;
                else
                    if( s[j]=='F' )   p[++cnt]=(node){ i,j+1 };
                    else   g[i][j+1]= s[j]=='#' ? -1 : INF ;
        }
        for(int i=1;i<=cnt;i++)   Prepare( p[i].x,p[i].y );
        bfs( sx,sy );
        for(int i=1;i<=n;i++)   ans=min( min( ans,dis[i][1] ),dis[i][m] );
        for(int i=1;i<=m;i++)   ans=min( min( ans,dis[1][i] ),dis[n][i] );
        printf( ans==INF ? "IMPOSSIBLE\n" : "%d\n",ans+1 );
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值