88 lines
2.6 KiB
C++
88 lines
2.6 KiB
C++
#include <bits/stdc++.h>
|
||
|
||
using namespace std;
|
||
const int INF = 0x3f3f3f3f;
|
||
const int N = 310;
|
||
|
||
//二维坐标系中每个点的上下左右变化delta坐标
|
||
int dx[] = {0, 0, -1, 1};
|
||
int dy[] = {1, -1, 0, 0};
|
||
|
||
int a[N][N]; //x,y坐标的最早被流星覆盖到的时间
|
||
int st[N][N]; //访问过的标识+从原点出发需要走几步到达这个位置
|
||
|
||
//定义结构体,x,y这个坐标,到达需要step步骤
|
||
struct coord {
|
||
int x, y;
|
||
};
|
||
|
||
//广度优先搜索
|
||
int bfs() {
|
||
queue<coord> q;
|
||
|
||
//出发的原点位置
|
||
q.push({0, 0});
|
||
|
||
//标识走过了0步,到达了这个位置
|
||
st[0][0] = 0;
|
||
|
||
//广度优先搜索的框架
|
||
while (!q.empty()) {
|
||
//队列首
|
||
coord u = q.front();
|
||
//出队列
|
||
q.pop();
|
||
//四个方向
|
||
for (int i = 0; i < 4; i++) {
|
||
int nx = u.x + dx[i];
|
||
int ny = u.y + dy[i];
|
||
//出了第一象限是不可以的
|
||
if (nx < 0 || ny < 0)continue;
|
||
|
||
//如果这个点为INF,表示永远不会被摧毁,已经安全了
|
||
if (a[nx][ny] == INF) return st[nx][ny] = st[u.x][u.y] + 1;
|
||
|
||
//如果到达这个时间点的时间早于最早摧毁时间,可以走
|
||
if (st[u.x][u.y] + 1 < a[nx][ny] && st[nx][ny] == -1) {
|
||
st[nx][ny] = st[u.x][u.y] + 1;
|
||
q.push({nx, ny});
|
||
}
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
int main() {
|
||
//初始化为INF(预求最小,先设最大)
|
||
memset(a, 0x3f, sizeof a);
|
||
|
||
//初始化为-1,表示没有走过
|
||
memset(st, -1, sizeof st);
|
||
|
||
//一共m个流星
|
||
int m;
|
||
cin >> m;
|
||
for (int i = 1; i <= m; i++) {
|
||
int x, y, t;
|
||
cin >> x >> y >> t;
|
||
|
||
//预处理的过程
|
||
//Q:预处理的是什么?
|
||
//A:每个点,都有一个最早的破坏时间,可能是直接被砸中,也可能是被牵连~,那么,这个点,
|
||
// 是什么时间被一次覆盖到呢?需要预处理出来
|
||
//求出该点和周围点的最早摧毁时间
|
||
a[x][y] = min(a[x][y], t); //如果直接砸中的时间小于原来记录的时间,需要修改一下。
|
||
for (int j = 0; j < 4; j++) {
|
||
//可以到达的新坐标位置
|
||
int nx = x + dx[j];
|
||
int ny = y + dy[j];
|
||
//一直在第一象限行动,只要nx,ny不小于0,可以随意向右,向上去走,右和上没有边界
|
||
if (nx >= 0 && ny >= 0) a[nx][ny] = min(a[nx][ny], t);
|
||
}
|
||
}
|
||
//广度优先搜索
|
||
printf("%d\n", bfs());
|
||
return 0;
|
||
}
|
||
|