3669 Meteor Shower

問題概要

座標平面上の格子点にM個の隕石が降ってくる。
それぞれの隕石の座標(xi,yi)および時間tiが与えられる。


マスに隕石が落ちると、それ以降、そのマスおよび接する4マスに立ち入ることはできなくなる。
最初Bessieは(0,0)にいて、第一象限を、時間1ごとに座標軸に平行に1だけ動けるとき、
Bessieが安全な場所まで移動するのにかかる最短時間を求めよ。
不可能な場合は-1を出力せよ。


M≦50000,0≦xi,yi≦300,ti≦1000を満たす。

解法

各マスについて、最初に隕石が降ってくる時間を求めておく。
その後、座標平面の(0,0)から幅優先探索で安全な地点を探す。

ソースコード

const int n=305,dy[]={-1,0,1,0,0},dx[]={0,-1,0,1,0};
int m,safe[n][n];
bool v[n][n];

int main()
{
	scanf("%d",&m);
	rep(i,n)rep(j,n)safe[i][j]=inf;
	rep(i,m)
	{
		int x,y,t; scanf("%d%d%d",&x,&y,&t);
		rep(d,5)
		{
			int ny=y+dy[d],nx=x+dx[d];
			if(0<=ny&&ny<n&&0<=nx&&nx<n)safe[ny][nx]=min(safe[ny][nx],t);
		}
	}
	queue<pair<int,pi> > Q; Q.push(mp(0,mp(0,0)));
	while(!Q.empty())
	{
		int y=Q.front().second.first,x=Q.front().second.second;
		int c=Q.front().first; Q.pop();
		if(v[y][x])continue;
		v[y][x]=1;
		if(safe[y][x]==inf)
		{
			printf("%d\n",c); return 0;
		}
		rep(d,4)
		{
			int ny=y+dy[d],nx=x+dx[d];
			if(0<=ny&&ny<n&&0<=nx&&nx<n&&!v[ny][nx]&&c+1<safe[ny][nx])
			Q.push(mp(c+1,mp(ny,nx)));
		}
	}
	puts("-1");
	return 0;
}