洛谷 P2895 [USACO08FEB] Meteor Shower S

思路:BFS

这是一道BFS的题母庸质疑,其实质上是一个迷宫问题。但是,又与迷宫问题有不同的地方,因为这里有干扰因素,所以我们说这种问题就是有限制条件的迷宫问题。

BFS的照常遍历是没有问题。在题目中我们还需要考虑这个人会不会被陨石砸到。这里在BFS中就需要特殊判断一下,也就是看看陨石降落的时候,这个人是在那个位置。如果说这个人走到这个位置的时候时刻大于陨石降落的时刻,我们就应该舍弃掉这种可能性;否则我们就可以走。

另外,在陨石降落的时候,可能是多颗,所以在陨石降落的时候,可能会烧到同一个地方,所以我们需要取其中最早砸到地面的陨石的时间,这一点很重要。

另外,在人行走的限制条件时,为什么没有规定最大上限呢?你可以定,但是没必要,因为我们在遍历到安全的地方就不会走了,所以无所谓。

还有,在初始化陨石的数组时(代码中fire就是代表陨石在这个坐标降落的时刻),需要初始化为无穷大,因为这样才能代表陨石不会降落到这个点上,然后我们再去更新数值,这样才是科学的。

上代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath> 
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include <iomanip>
#include<sstream>
#include<numeric>
#include<map>
#include<limits.h>
#include<set>
#define int long long
#define MAX 1010
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
typedef pair<int, int> PII;
int n, m;
int counts=INT_MAX;
int a, b;
int dx[] = { -1,1,0,0 };
int dy[] = { 0,0,-1,1 };
queue<PII>q;
int res = 0;
char maps[MAX][MAX];
int dist[MAX][MAX];
int fire[MAX][MAX];
int bfs() {
    q.push({ 0,0 });
    dist[0][0] = 0;
    while (!q.empty()) {
        auto tmp = q.front();
        q.pop();
        for (int i = 0; i < 4; i++) {
            int a = tmp.first + dx[i];
            int b = tmp.second + dy[i];

            if (a < 0 || b < 0)continue;
            if (dist[a][b])continue;
            if (dist[tmp.first][tmp.second]+1 >= fire[a][b])continue;

            dist[a][b] = dist[tmp.first][tmp.second] + 1;
            q.push({ a,b });
            if (fire[a][b]>1e9)
                return dist[a][b];
        }
    }
    return -1;
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> n;
    memset(fire, 0x3f, sizeof fire);
    while (n--) {
        int x, y, t;
        cin >> x >> y >> t;
        fire[x][y] = min(fire[x][y], t);
        for (int i = 0; i < 4; i++) {
            int a = dx[i] + x;
            int b = dy[i] + y;

            if (a < 0 || a>301 || b < 0 || b>301)
                continue;
            fire[a][b] = min(fire[a][b], t);
        }
    }
    int res = bfs();
    cout << res;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值