UVA - 11624 Fire! (两遍bfs)

本文介绍了一种使用两次广度优先搜索(BFS)解决迷宫火灾逃生问题的方法。首先,通过一次BFS计算出每个位置着火的时间,然后再次运行BFS来找到人物能够逃离迷宫的最短路径及时间。此算法确保了在火灾蔓延的同时,人物可以找到最佳的逃生路线。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:有一个迷宫, 迷宫中若干处方块着火了, 人每走一步, 火就往四周扩散一圈, 问人可不可以逃出迷宫并且求出逃出迷宫所需最短时间。

题解:跑两遍BFS, 第一遍求出每个点的着火时间, 第二遍求出人能跑出去的最短时间。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 100000 + 10
#define MAXN 1000 + 10

using namespace std;
typedef unsigned long long ll;
const ll MOD = 1e9 + 7;

char maze[MAXN][MAXN];
int visit[MAXN][MAXN] = {0};
int fire[MAXN][MAXN] = {0};
int op[2][4] = {{1, -1, 0, 0},
                {0, 0, -1, 1}};

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

int main()
{
    int T;
    while(~scanf("%d", &T)){

        while(T--){

            memset(visit, 0, sizeof(visit));
            int R, C;
            scanf("%d %d", &R, &C);
            for(int i = 0; i < R; i ++)
                scanf("%s", maze[i]);
            for(int i = 0; i < R; i ++)
                for(int j = 0; j < C; j ++)
                    fire[i][j] = 3000;

            queue<node> q;
            node temp;
            for(int i = 0;i < R;i ++){
                for(int j = 0; j < C; j ++){
                    if(maze[i][j] == 'F'){
                        temp.x = i;
                        temp.y = j;
                        temp.t = 0;
                        q.push(temp);
                        fire[i][j] = 0;
                        visit[i][j] = 1;
                    }
                }
            }

            while(!q.empty()){
                int x = q.front().x;
                int y = q.front().y;
                int t = q.front().t;
                q.pop();
                for(int i = 0; i < 4; i ++){
                    int xx = x + op[0][i], yy = y + op[1][i];
                    if(xx >= 0 && xx < R && yy >= 0 && yy < C &&
                        visit[xx][yy] == 0 && maze[xx][yy] != '#'){
                            temp.x = xx;
                            temp.y = yy;
                            temp.t = t + 1;
                            fire[xx][yy] = t + 1;
                            q.push(temp);
                            visit[xx][yy] = 1;
                    }
                }
            }
            memset(visit, 0, sizeof(visit));
            for(int i = 0; i < R; i ++){
                for(int j = 0; j < C; j ++){
                    if(maze[i][j] == 'J'){
                        temp.x = i;
                        temp.y = j;
                        temp.t = 0;
                        q.push(temp);
                        visit[i][j] = 1;
                        break;
                    }
                }
            }
            int flag = 0;
            int ans;
            while(!q.empty()){
                int x = q.front().x;
                int y = q.front().y;
                int t = q.front().t;
                q.pop();
                if(x == 0 || x == R - 1 || y == 0 || y == C - 1){
                    flag = 1;
                    ans = t + 1;
                    break;
                }
                for(int i = 0; i < 4; i ++){
                    int xx = x + op[0][i], yy = y + op[1][i];
                    if(xx >= 0 && xx < R && yy >= 0 && yy < C &&
                        visit[xx][yy] == 0 && maze[xx][yy] != '#' && t + 1 < fire[xx][yy]){
                            temp.x = xx;
                            temp.y = yy;
                            temp.t = t + 1;
                            q.push(temp);
                            visit[xx][yy] = 1;
                    }
                }
            }
            if(flag)
                printf("%d\n", ans);
            else
                printf("IMPOSSIBLE\n");
        }
    }
}


/*

The WAM is F**KING interesting .

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值