21.Meteor Shower S

# P2895 [USACO08FEB] Meteor Shower S

## 题目描述

贝茜听说一场特别的流星雨即将到来:这些流星会撞向地球,并摧毁它们所撞击的任何东西。她为自己的安全感到焦虑,发誓要找到一个安全的地方(一个永远不会被流星摧毁的地方)。

如果将牧场放入一个直角坐标系中,贝茜现在的位置是原点,并且,贝茜不能踏上一块被流星砸过的土地。

根据预报,一共有 $M$ 颗流星 $(1\leq M\leq 50,000)$ 会坠落在农场上,其中第 $i$ 颗流星会在时刻 $T_i$($0 \leq T _ i \leq 1000$)砸在坐标为 $(X_i,Y_i)(0\leq X_i\leq 300$,$0\leq Y_i\leq 300)$ 的格子里。流星的力量会将它所在的格子,以及周围 $4$ 个相邻的格子都化为焦土,当然贝茜也无法再在这些格子上行走。

贝茜在时刻 $0$ 开始行动,她只能在会在横纵坐标 $X,Y\ge 0$ 的区域中,平行于坐标轴行动,每 $1$ 个时刻中,她能移动到相邻的(一般是 $4$ 个)格子中的任意一个,当然目标格子要没有被烧焦才行。如果一个格子在时刻 $t$ 被流星撞击或烧焦,那么贝茜只能在 $t$ 之前的时刻在这个格子里出现。 贝茜一开始在 $(0,0)$。

请你计算一下,贝茜最少需要多少时间才能到达一个安全的格子。如果不可能到达输出 $−1$。

## 输入格式

共 $M+1$ 行,第 $1$ 行输入一个整数 $M$,接下来的 $M$ 行每行输入三个整数分别为 $X_i, Y_i, T_i$。

## 输出格式

贝茜到达安全地点所需的最短时间,如果不可能,则为 $-1$。

## 输入输出样例 #1

### 输入 #1

```
4
0 0 2
2 1 2
1 1 2
0 3 5
```

### 输出 #1

```
5
```

#include<bits/stdc++.h>
using namespace std;
const int N =305;
int gt[N][N];
int st[N][N];
int dist[N][N];
int dx[]={-1,0,1,0};
int dy[]={0,-1,0,1};
typedef pair<int,int> PII;
queue<PII> q;
int m;

int bfs(int x,int y)
{
    memset(dist,-1,sizeof(dist));
    dist[x][y]=0;
    q.push({x,y});
    while(q.size())
    {
        auto t=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int a=t.first+dx[i],b=t.second+dy[i];
            if(a<0||b<0) continue; //边界
            if(dist[a][b]!=-1) continue;  //访问过的点
            if(gt[a][b]<=dist[t.first][t.second]+1) continue; //格子化为焦土 时间等于也不可以
            q.push({a, b});
            dist[a][b]=dist[t.first][t.second]+1;
            
            if (gt[a][b] >= 1000000000 ) return dist[a][b];
        }
    }
    
    return -1;
}
int main()
{
    cin>>m;
    memset(gt,0x3f3f3f3f,sizeof(gt));  //把安全的地方全部初始化为一个极大的数
    for(int i=1;i<=m;i++)
    {
        int x,y,t;
        cin>>x>>y>>t;
        gt[x][y]=min(t,gt[x][y]);  //当有第二个流星落到同样的格子时,时间应该去最小值
        for(int j=0;j<4;j++)
        {
            int a=x+dx[j],b=y+dy[j];
            if(a>=0&&a<=300&&b>=0&&b<=300) 
                gt[a][b]=min(t,gt[a][b]);  //蔓延四个格子同理
        }
    }
    int res=bfs(0,0); 
    cout<<res;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值