FZU 2196 Escape (两次bfs)

题意:

小明进入地下迷宫寻找宝藏,找到宝藏后却发生地震,迷宫各处产生岩浆,小明急忙向出口处逃跑。如果丢下宝藏,小明就能迅速离开迷宫,但小明并不想轻易放弃自己的辛苦所得。所以他急忙联系当程序员的朋友你(当然是用手机联系),并告诉你他所面临的情况,希望你能告诉他是否能成功带着宝藏逃脱。

题解:

首先用Spfa预处理出火到达每个位置时间。然后这个人从起点开始bfs,注意一点如果火和人同时到达终点人可以逃脱!!!这个有点坑!手写队列开小了,一直wa。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const int MOD=1000000007;
const double eps = 1e-9;
const int maxn = 1005;
int rock[maxn][maxn];
char maze[maxn][maxn];
int Time[maxn][maxn], vis[maxn][maxn];
int n,m;
struct Node{
    int x, y;
    Node(){}
    Node(int a, int b){
        x = a;
        y = b;
    }
};
Node Q[maxn * maxn];
int f, r;
int d[4][2]={
  {1, 0},{0, 1},{-1, 0},{0, -1}
};

bool ok(int x, int y){
    if(x >= 1 && x <= n && y >= 1 && y <= m)
        if(maze[x][y] != '!' && maze[x][y] != '#')
            return true;
    return false;
}

Node Init(){
    scanf("%d %d", &n, &m);
    Node s;
    memset(rock, 0x3f, sizeof rock);
    memset(vis, 0, sizeof vis);
    f = r = 0;
    for(int i = 1; i <= n; i++){
        scanf("%s", maze[i] + 1);
        for(int j = 1; j <= m; j++){
            if(maze[i][j] == '!'){
                Q[r++] = Node(i, j);
                vis[i][j] = 1;
                rock[i][j] = 0;
            }
            if(maze[i][j] == 'S')s = Node(i, j);
        }
    }
    Node now;
    int x, y;
    while(f < r){
        now = Q[f++];
        vis[now.x][now.y] = 0;
        for(int i = 0; i < 4; i++){
            x = now.x + d[i][0];
            y = now.y + d[i][1];
            if(ok(x, y)){
                if(rock[now.x][now.y] + 1 < rock[x][y]){
                    rock[x][y] = rock[now.x][now.y] + 1;
                    if(!vis[x][y]){
                        vis[x][y] = 1;
                        Q[r++] = Node(x, y);
                    }
                }
            }
        }
    }
    return s;
}


void bfs(Node s){
    memset(vis, 0, sizeof vis);
    memset(Time, 0x3f, sizeof Time);
    f = r = 0;
    Q[r++] = s;
    Time[s.x][s.y] = 0;
    vis[s.x][s.y] = 1;
    Node now;
    int x, y;
    while(f < r){
        now = Q[f++];
        for(int i = 0; i <4; i++){
            x = now.x + d[i][0];
            y = now.y + d[i][1];
            if(ok(x, y) && !vis[x][y]){
                if(maze[x][y] == '.'){
                    if(Time[now.x][now.y] + 1 < rock[x][y])
                        if(Time[now.x][now.y] + 1 < Time[x][y]){
                            Time[x][y] = Time[now.x][now.y] + 1;
                            Q[r++] = Node(x, y);
                        }
                }else if(maze[x][y] == 'E'){
                    if(Time[now.x][now.y] + 1 <= rock[x][y]){
                        printf("Yes\n");
                        return ;
                    }
                }
            }
        }
    }
    printf("No\n");
}

int main(){
    //freopen("E:\\read.txt","r",stdin);
    int T;
    scanf("%d", &T);
    while(T--){
        bfs(Init());
    }
    return 0;
}
/*
100
3 4
!S..
....
...E

3 4
.S..
.!..
...E


3 4
.S..
...#
..#E


3 4
....
...S
..!E

1
1 3
!ES
*/


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值