题目大意
有一个矩形棋盘,某些格点在某时刻起不再能通行。从 ( 0 , 0 ) (0,0) (0,0) 开始以 1/s 的速度移动到一个永远安全的点,求最短时间。
解题思路
广度优先搜索即可。病历本:流星只能砸 300 以内,但人可以走 300 以外。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define min(x,y) ((x)<(y)?(x):(y))
const int MAXM=50010;
const int MAXN=320;
struct node{
int x, y;
node (){
x=y=0;
}
}q[MAXN*MAXN*2];
int t[MAXN][MAXN], lmt[MAXN][MAXN];
int qd[MAXN][MAXN]; //是否在队列里
int m;
int sx, sy, sz;
int ans=0x3f3f3f3f;
int fx[6]={0, 0, 0, -1, 1};
int fy[6]={0, -1, 1, 0, 0};
void update (int x, int y, int st){
if (0>x||0>y||310<x||310<y) return;
lmt[x][y]=min (lmt[x][y], st);
}
void bfs (){
int st=1, ed=2;
while (st<ed){
// printf ("%d %d\n", q[st].x, q[st].y);
// system ("pause>nul");
for (int i=1; i<=4; ++i){
int nx=q[st].x+fx[i], ny=q[st].y+fy[i];
if (0>nx||0>ny||310<nx||310<ny) continue;
if (t[q[st].x][q[st].y]+1>=lmt[nx][ny]) continue;
if (lmt[nx][ny]>1e8) ans=min (ans, t[q[st].x][q[st].y]+1);
if (t[nx][ny]>t[q[st].x][q[st].y]+1){
t[nx][ny]=t[q[st].x][q[st].y]+1;
if (!qd[nx][ny]){
q[ed].x=nx; q[ed].y=ny;
++ed; qd[nx][ny]=1;
}
}
}
qd[q[st].x][q[st].y]=0;
++st;
}
}
inline int read (){
int s=0; char c;
do c=getchar (); while ('0'>c||'9'<c);
while ('0'<=c&&'9'>=c)
s=s*10+c-48, c=getchar ();
return s;
}
int main (){
memset (qd, 0, sizeof (qd));
memset (t, 0x3f3f3f, sizeof (t)); t[0][0]=0;
memset (lmt, 0x3f3f3f, sizeof (lmt));
m=read ();
for (int i=1; i<=m; ++i){
sx=read (); sy=read (); sz=read ();
for (int j=0; j<=4; ++j)
update (sx+fx[j], sy+fy[j], sz);
}
// for (int i=0; i<=4; ++i){
// for (int j=0; j<=4; ++j)
// printf ("%d ", lmt[i][j]);
// puts("");
// }
bfs ();
if (ans>1e8) ans=-1;
printf ("%d", ans);
}