Meteor Shower
Bessie听说一场非凡的流星雨即将来临; 据报道,这些流星将坠入地球并摧毁他们击中的任何东西。为了安全起见,她发誓要找到一个安全的地方(一个永远不被流星摧毁的地方)。她目前正在坐标平面的原点放牧,并希望搬到一个新的,更安全的地方,同时避免被沿途的流星摧毁。
据报告说,M颗流星(1≤ M ≤50000)将会坠入,流星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
第1行:Bessie到达安全地点所需的最短时间,如果不可能,则为-1。
Sample Input
4
0 0 2
2 1 2
1 1 2
0 3 5
Sample Output
5
C++编写:
这道题的相邻直线点可能有点难以理解,此处简单地解释一下,假如在某一时刻一颗流星撞击点(3,3),那么该时间点被摧毁的地方有五个——(3,3)、(3,2)、(3,4)、(2,3)、(4,3),其他的应该没有什么难理解的了,下面是代码:
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAX_M=50010;
const int MAX_N=310;
int map[MAX_N][MAX_N];
int d[MAX_N][MAX_N];
int dx[5]={1,0,-1,0,0},dy[5]={0,1,0,-1,0};
int m,x,y,t;
typedef pair<int,int> P;
struct Meteor {
int x;
int y;
int t;
} meteors[MAX_M];
bool compare (Meteor a, Meteor b)
{
if (a.t < b.t) return true;
else return false;
}
bool check(int x,int y)
{
if(x>=0 && x<MAX_N && y>=0 && y<MAX_N) return true;
else return false;
}
int bfs()
{
queue<P> que;
if(map[0][0] == 0) return -1;
else if(map[0][0] == INF) return 0;
que.push(P(0,0));
while(que.size())
{
P p=que.front();
que.pop();
int px=p.first,py=p.second;
if (px >= MAX_N || py >= MAX_N) continue; //这句话仅用于一种保护措施,基本不可能执行这行代码
for(int i=0;i<4;i++)
{
int nx=px+dx[i],ny=py+dy[i];
if(check(nx,ny))
{
if(map[nx][ny] == INF) //该点永远不会被摧毁
{
return ++d[px][py];
}
if(d[px][py]+1 < map[nx][ny] && !d[nx][ny]) //在该点被摧毁之前到达并且这个点还没有被走过
{ //这里有点绕,这个点被走过了之后就不能再回来了吗
que.push(P(nx, ny)); //这个点早晚要被摧毁,同时我们要求的是最短时间
d[nx][ny] = d[px][py] + 1; //再走一次其实是耽搁一次时间,故没有必要再走
}
}
}
}
return -1;
}
void solve()
{
for(int i=0;i<MAX_N;i++)
{
for(int j=0;j<MAX_N;j++)
{
map[i][j]=INF; //初始化数组
}
}
for(int i=0;i<m;i++)
cin>>meteors[i].x>>meteors[i].y>>meteors[i].t;
sort(meteors, meteors + m, compare); //按t从小到大排列
for(int i=0;i<m;i++)
{
for(int j=0;j<5;j++)
{
int nx=meteors[i].x,ny=meteors[i].y;
nx += dx[j];
ny += dy[j];
if(check(nx,ny) && map[nx][ny]>meteors[i].t) //记录一个点被摧毁的最早时间
map[nx][ny] = meteors[i].t;
}
}
cout<<bfs()<<endl;
}
int main()
{
ios::sync_with_stdio(false);
while(cin>>m)
solve();
}