【BFS】UVA 11624 Fire!

【题目】https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2671

【题意】#是墙,J是人,F是火,火每1秒会向四周蔓延1格,问J最快能在几秒跑出图外,不能则输出IMPOSSIBLE

【思路】一开始思路是用每个F跑BFS更新所有点的最早着火时间,再从J跑BFS看能不能跑出去。然而T了...其实可以将所有的F一次性入队,跑一次BFS就行了,每个F一开始一定是最优的更新。

【代码】

#include<bits/stdc++.h>
#define fuck(x) std::cout<<"["<<#x<<"->"<<x<<"]"<<endl;
using namespace std;
typedef long long ll;

const int M=2e5+5;
const int inf=1e9+5;

int to[4][2]= {1,0,0,1,0,-1,-1,0};
char mp[1005][1005];
int fire[1005][1005];
int vis[1005][1005];
int n,m;
int jx,jy;
int ans;

struct node
{
    int x,y,step;
};

queue<node>q;

void bfsf()
{
    node t;
    while(!q.empty())
    {
        t=q.front();
        q.pop();
        fire[t.x][t.y]=min(fire[t.x][t.y],t.step);
        for(int i=0; i<4; i++)
        {
            if(t.x+to[i][0]<0||t.x+to[i][0]>=n||t.y+to[i][1]<0||t.y+to[i][1]>=m)
                continue;
            if(mp[t.x+to[i][0]][t.y+to[i][1]]=='#')
                continue;
            if(vis[t.x+to[i][0]][t.y+to[i][1]]==1)
                continue;
            vis[t.x+to[i][0]][t.y+to[i][1]]=1;
            q.push({t.x+to[i][0],t.y+to[i][1],t.step+1});
        }
    }
}

void bfsj(int x,int y)
{
    while(!q.empty())
        q.pop();
    node t{x,y,0};
    vis[x][y]=1;
    q.push(t);
    while(!q.empty())
    {
        t=q.front();
        q.pop();
        if(t.x==0||t.y==0||t.x==n-1||t.y==m-1)
        {
//            fuck(t.step);
//            fuck(t.x);
//            fuck(t.y);
            ans=min(ans,t.step+1);
        }
        for(int i=0; i<4; i++)
        {
            if(t.x+to[i][0]<0||t.x+to[i][0]>=n||t.y+to[i][1]<0||t.y+to[i][1]>=m)
                continue;
            if(mp[t.x+to[i][0]][t.y+to[i][1]]=='#')
                continue;
            if(t.step+1>=fire[t.x+to[i][0]][t.y+to[i][1]])
                continue;
            if(vis[t.x+to[i][0]][t.y+to[i][1]]==1)
                continue;
            vis[t.x+to[i][0]][t.y+to[i][1]]=1;
            q.push({t.x+to[i][0],t.y+to[i][1],t.step+1});
        }
    }
}

int main()
{

    int T;
    scanf("%d",&T);
    while(T--)
    {
        while(!q.empty())
            q.pop();
        ans=inf;
        fill(fire[0],fire[0]+1005*1005,inf);
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
        {
            scanf("%s",mp[i]);
            for(int j=0; j<m; j++)
            {
                if(mp[i][j]=='J')
                    jx=i,jy=j;
            }
        }
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(mp[i][j]=='F')
                {
                    q.push({i,j,0});
                }
            }
        }
        memset(vis,0,sizeof(vis));
        bfsf();
        memset(vis,0,sizeof(vis));
        bfsj(jx,jy);
        if(ans!=inf)
            printf("%d\n",ans);
        else
            printf("IMPOSSIBLE\n");
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值