Fire! UVA - 11624

2 篇文章 0 订阅

一定仔细看题目 一定要理解题意!!
题目意思是说在一个迷宫里 Joe 要在火烧到他之前逃出迷宫,只要Joe抵达迷宫的边界,就算是成功,输入中J代表Joe的位置,F代表火的位置,这里注意,F可以有多个位置。就是两边BFS,第一遍BFS确定图中每个点被火点燃时的时间,第二遍就是Joe行走。
这里根据输入,如果是#,即围墙区域,就设为-1,可以行走的区域设为INF,火的位置设为0(在第0分钟的时候,这块区域燃烧),通过第一遍BFS,计算出每块区域被点燃时的时间,第二遍BFS,只要人物行走时的时间小于这块区域被点燃的时间,人物即可通过

//leehaoze
#include <iostream>
#include <deque>
#include <string>
#include <vector>
#include <queue>
#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cstdio>
#include <cmath>
#include <cstdlib>

using namespace std;
const int INF = 1<<29;
#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
#define ULL unsigned long long

#define MAXN (10000)

struct Pos{
    Pos():time_(0){}
    Pos(int x,int y,int time):x_(x),y_(y),time_(time){}
    int x_,y_,time_;
};


int Move_X[] = {0, 0, 1,-1};
int Move_Y[] = {1,-1, 0, 0};

int R,C;
int map[MAXN][MAXN];
bool visit[MAXN][MAXN];
vector<Pos> F;
Pos J;

void Print(){
    for (int i = 0; i <= R + 1; ++i) {
        for (int j = 0; j <= C + 1; ++j) {
            cout << map[i][j] << ' ';
        }
        cout << endl;
    }
}


void Init(){
    for (int i = 0; i <= R + 1; ++i) {
        map[i][0] = INF;
        map[i][C + 1] = INF;
    }
    for (int j = 0; j <= C + 1; ++j) {
        map[0][j] = INF;
        map[R + 1][j] = INF;
    }
}


void Input(){
    F.clear();
    cin >> R >> C;
    for (int i = 1; i <= R; ++i) {
        for (int j = 1; j <= C; ++j) {
            char temp;
            cin >> temp;
            if(temp == '.'){
                map[i][j] = INF;
            }
            else if(temp == '#'){
                map[i][j] = -1;
            }
            else if(temp == 'J'){
                J.x_ = i;
                J.y_ = j;
                map[i][j] = INF;
            }
            else if(temp == 'F'){
                F.push_back(Pos(i,j,0));
                map[i][j] = INF;
            }
        }
    }
}

bool Legal_Burn(int dx,int dy){
    return dx >= 1 && dx <= R && dy >= 1 && dy <= C && !visit[dx][dy] && map[dx][dy] == INF;
}

void Burn(){
    memset(visit,false,sizeof visit);
    queue<Pos>Q;
    int size = F.size();
    for (int i = 0; i < size; ++i) {
        Q.push(F[i]);
        visit[F[i].x_][F[i].y_] = true;
    }
    while(!Q.empty()){
        Pos now = Q.front();
        Q.pop();
        map[now.x_][now.y_] = now.time_;
        for (int i = 0; i < 4; ++i) {
            int dx = now.x_ + Move_X[i];
            int dy = now.y_ + Move_Y[i];
            if(Legal_Burn(dx,dy)){
                visit[dx][dy] = true;
                Q.push(Pos(dx,dy,now.time_ + 1));
            }
        }
    }
}

bool Escape(Pos &now){
    return now.x_ == 0 || now.x_ == (R + 1) || now.y_ == 0 || now.y_ == (C + 1);
}

bool Legal(int dx,int dy,int time){
    return dx >= 0 && dx <= (R + 1) && dy >= 0 && dy <= (C + 1) && !visit[dx][dy] && time < map[dx][dy];
}

int Run(){
    memset(visit,false,sizeof visit);
    queue<Pos> Q;
    Q.push(J);
    visit[J.x_][J.y_] = true;
    while(!Q.empty()){
        Pos now = Q.front();
        Q.pop();
        if(Escape(now)){
            return now.time_;
        }
        for (int i = 0; i < 4; ++i) {
            int dx = now.x_ + Move_X[i];
            int dy = now.y_ + Move_Y[i];
            if(Legal(dx,dy,now.time_ + 1)){
                visit[dx][dy] = true;
                Q.push(Pos(dx,dy,now.time_ + 1));
            }
        }
    }
    return -1;
}

int main() {
#ifdef LOCAL
    freopen("IN.txt", "r", stdin);
#endif
    int T;
    cin >> T;
    while(T--){
        Input();
        Init();
        Burn();
        int ans = Run();
        if(ans == -1){
            cout << "IMPOSSIBLE" << endl;
        }
        else{
            cout << ans << endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值