【题解】Meteor Shower POJ - 3669 ⭐⭐⭐ 【Bfs 剪枝】

Meteor Shower POJ - 3669

Bessie听说有场史无前例的流星雨即将来临;有谶言:陨星将落,徒留灰烬。为保生机,她誓将找寻安全之所(永避星坠之地)。目前她正在平面坐标系的原点放牧,打算在群星断其生路前转移至安全地点。

此次共有M (1 ≤ M ≤ 50,000)颗流星来袭,流星i将在时间点Ti (0 ≤ Ti ≤ 1,000) 袭击点 (Xi, Yi) (0 ≤ Xi ≤ 300; 0 ≤ Yi ≤ 300)。每颗流星都将摧毁落点及其相邻四点的区域。

Bessie在0时刻时处于原点,且只能行于第一象限,以平行与坐标轴每秒一个单位长度的速度奔走于未被毁坏的相邻(通常为4)点上。在某点被摧毁的刹那及其往后的时刻,她都无法进入该点。

寻找Bessie到达安全地点所需的最短时间。

Input

  • 第1行: 一个整数: M
  • 第2…M+1行: 第i+1行包含由空格分隔的三个整数: Xi, Yi, and Ti

Output

  • 仅一行: Bessie寻得安全点所花费的最短时间,无解则为-1。

Examples

Sample Input - 输入样例
4
0 0 2
2 1 2
1 1 2
0 3 5
Sample Output - 输出样例
5

Hint




题解:

二维数组存一下当前(x,y)坐标的时间, 每次要走过后要更新数组, 不然会T
注意人是可以走过300的

经验小结:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const int inf = 1 << 30;
const int maxn = 310;
const int maxm = 50010;

struct node{
    int x, y, t;
};
int maze[maxn][maxn]; //每一个坐标的时间
int act[5][2] = {{0,0},{1,0},{0,1},{0,-1},{-1,0}};
bool judge(int x, int y){
    return x>=0&&y>=0;
}
int Bfs(){
    queue<node> q;
    if(maze[0][0] > 0)
        q.push(node{0, 0, 0});
    while(!q.empty()){
        node cur = q.front();
        q.pop();
        int x = cur.x, y = cur.y, t = cur.t;
        if(maze[x][y] == inf)
            return t;
        int cx, cy;
        for(int i = 1; i < 5; ++i){
            cx = x+act[i][0], cy = y+act[i][1];
            if(cx>=0&&cy>=0 && t+1 < maze[cx][cy]){
                if(maze[cx][cy]!=inf)
                    maze[cx][cy] = t+1; //最优化剪枝
                q.push(node{cx, cy, t+1});
            }
        }
    }
    return -1;
}
int main() {
    ios::sync_with_stdio(false);
    fill(maze[0], maze[0]+maxn*maxn, inf);
    int M, x, y, t;
    cin >> M;
    for(int i = 1; i <= M; ++i){
        cin >> x >> y >> t;
        int cx, cy;
        for(int i = 0; i < 5; ++i){
            cx = x+act[i][0], cy = y+act[i][1];
            if(cx>=0&&cx<=300&&cy>=0&&cy<=300)
                maze[cx][cy] = min(maze[cx][cy], t);
        }
    }
    cout << Bfs() << endl;

    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值