【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为常数

代码

#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;
}
posted @ 2017-10-13 14:36  清疚  阅读(88)  评论(0)    收藏  举报