UVA11624 Fire(两次BFS+数组记录)

题意

给定一个n*m的矩阵,其中‘J’表示人,‘F’表示火,‘#’表示墙,‘.’表示通道。火每分钟朝四周蔓延一个格子,人每分钟也只能从四周走一个格子,为墙的格子火和人都不能走。求人能否逃出矩阵。

解题

先从火开始进行bfs,并用d[i][j]表示火到达第i行第j列所需的最短时间。再从人开始bfs,加一个到下一个格子的时间必须小于d[i][j]的限制。

一开始TLE了一发,想了想就进行了两次bfs是不太会TLE的。重新读题注意到题目特别指出人只有一个,也就是说火可能有多个。所以,按我原来的写法,对每个火都进行了一次bfs,超时就是可以预见的了。故一开始将火放入队列,只进行一次bfs即可解决超时问题。

AC代码

//160ms
#include 
#include 
#include 
#include 
#include 
using namespace std;

const int maxn=1e3+100;
char s[maxn][maxn];
int n,m;
int d[maxn][maxn];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
bool vis[maxn][maxn];
struct node
{
    int x,y,t;
    node(int x,int y,int t):x(x),y(y),t(t){}
};
bool valid(int x,int y)
{
    return x>=0 && x=0 && y'.';
}
queue Q;
void bfs(char ch,int u,int v)
{
    memset(vis,false,sizeof(vis));
    if(ch=='F') memset(d,0x3f,sizeof(d));
    if(ch=='J')
    {
        vis[u][v]=true;
        Q.push(node(u,v,0));
    }
    while(!Q.empty())
    {
        node now=Q.front();Q.pop();
        int x=now.x,y=now.y,t=now.t;
       // cout<
        if(ch=='J')
        {
            if(x==n-1 || y==m-1 || x==0 || y==0)
            {
                printf("%d\n",t+1);
                return ;
            }
        }
        for(int i=0;i<4;i++)
        {
            int fx=x+dir[i][0],fy=y+dir[i][1];
           // cout<<"fx="<if(!valid(fx,fy)) continue;
            if(ch=='J' && d[fx][fy]<=t+1) continue;
            vis[fx][fy]=true;
            if(ch=='F') d[fx][fy]=t+1;
            Q.push(node(fx,fy,t+1));
        }
    }
    if(ch=='J') printf("IMPOSSIBLE\n");
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        while(!Q.empty()) Q.pop();
        scanf("%d%d",&n,&m);
        for(int i=0;iscanf("%s",s[i]);
        for(int i=0;ifor(int j=0;jif(s[i][j]=='F')
            {
                Q.push(node(i,j,0));
               // bfs('F',i,j);
            }
        bfs('F',0,0);
        for(int i=0;ifor(int j=0;jif(s[i][j]=='J') bfs('J',i,j);
    }
    return 0;
}

你可能感兴趣的:(图论,DFS&BFS)