#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std; const int maxn = ;
const int INF = ;
int M;
struct Meteor {
int X, Y;
int Time; //Time_i
Meteor(int X = , int Y = , int T = ) :
X(X), Y(Y), Time(T) {}
bool operator < (const Meteor& b) { // 升序排序
return Time < b.Time;
}
} meteor[ + ];
int dir[][] = {{-, }, {, }, {, }, {, -}, {, }};
bool used[maxn][maxn];
int field[maxn][maxn]; //标记好每个位置被流星砸(以及扩散到)的时间
int last;
int ans; void input();
void solve();
bool check(int r, int c, int T);
int BFS(int r, int c, int T); void input()
{
memset(used, false, sizeof(used));
for (int i = ; i < maxn; i++) {
for (int j = ; j < maxn; j++) {
field[i][j] = INF;
}
}
scanf("%d", &M);
for (int i = ; i < M; i++) {
scanf("%d%d%d", &meteor[i].X, &meteor[i].Y, &meteor[i].Time);
}
sort(meteor, meteor + M); //按照时间升序排序
last = meteor[M - ].Time; //最后被毁灭的时间 for (int i = ; i < M; i++) //M个火球
{
for (int j = ; j < ; j++) { //5个方向
int x = meteor[i].X + dir[j][],
y = meteor[i].Y + dir[j][];
if ( check(x, y, meteor[i].Time) ) {
field[x][y] = meteor[i].Time; //x,y位置和周围扩散位置,破坏的时间
}
}
}
} bool check(int r, int c, int T)
{
return r >= && c >= && field[r][c] > T;
} int BFS(int r, int c, int T)
{
used[r][c] = true; //从原点开始
queue<Meteor> que;
Meteor cur;
cur.X = r, cur.Y = c, cur.Time = T;
que.push(cur); //开始的位置,和时间 while (!que.empty())
{
Meteor m = que.front(); que.pop();
for (int i = ; i < ; i++) { //遍历4个方向, 因为最后一个方向,是在原地
cur = m;
cur.X = m.X + dir[i][],
cur.Y = m.Y + dir[i][]; //周围位置
cur.Time++; //移到下个位置的时间
//如果火球落到该位置的时间>当前人的时间,表示还有机会移动
if (check(cur.X, cur.Y, cur.Time) && !used[cur.X][cur.Y]) {
used[cur.X][cur.Y] = true;
//说明当前位置时间永远不会被炸到
//last是最后被炸到的时间
if (field[cur.X][cur.Y] > last) {
return cur.Time; //则返回当前到达安全的时间
}
que.push(cur); //否则入队列
}
}
}
return -; //不存在安全位置
} void solve()
{
input();
if (field[][] == ) { //原点就被毁灭, 反应时间为0
printf("-1\n");
}
else {
printf("%d\n", BFS(, , ));
}
} int main()
{
solve();
return ;
}
分析:1. 还是经典的BFS问题,主要是要 对被摧毁的位置的时间进行记录(先升序处理)(以及波及到的位置进行时间标志).
2. 人行打算走下一步的时候, 先判断是否时间允许,允许标志为访问过(允许的时候,需要当前位置时间是否已经超过了 最后被毁灭位置的时间,是则返回 到达该安全位置的时间)。不允许则添加到队列中。