#include 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 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; }