[USACO08FEB]Meteor Shower S
题解
我们用 \(a[i][j]\) 表示坐标 \((i,j)\) 最先在哪一时刻被撞击,分两种情况:
- 如果没有陨石撞击,我们将其赋上极值1001,因为 \(0 \le T_i \le 1000\)。
- 如果有陨石撞击,因为可能会有多次,我们取最小的时间。
所以,初始化坐标系代码如下:
for(int i=0;i<=310;i++)
for(int j=0;j<=310;j++)
a[i][j]=1001;
for(int i=1,x,y,t;i<=n;i++)
{
read(x);read(y);read(t);
a[x][y]=min(a[x][y],t);
for(int j=0;j<=3;j++)
{
int tx=x+dx[j],ty=y+dy[j];
if(tx>=0&&ty>=0)a[tx][ty]=min(a[tx][ty],t);
}
}
最后从 \((0,0)\) 开始 BFS。
Code:
#include<bits/stdc++.h>
using namespace std;
void read(int &x)
{
char ch=getchar();
int r=0,w=1;
while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
x=r*w;
}
int a[350][350],f[350][350];
struct kkk
{
int x,y,step;
};
queue<kkk>q;
int dx[]={0,-1,0,1};
int dy[]={-1,0,1,0};
void bfs()
{
f[0][0]=1;
q.push(kkk{0,0,0});
while(!q.empty())
{
kkk t=q.front();
q.pop();
if(a[t.x][t.y]==1001)
{
printf("%d",t.step);
return;
}
for(int i=0;i<=3;i++)
{
int tx=t.x+dx[i],ty=t.y+dy[i];
if(tx>=0&&tx<=310&&ty>=0&&ty<=310&&!f[tx][ty]&&t.step+1<a[tx][ty])
q.push(kkk{tx,ty,t.step+1}),f[tx][ty]=t.step+1;
}
}
printf("-1");
}
int main()
{
int n;
read(n);
for(int i=0;i<=310;i++)
for(int j=0;j<=310;j++)
a[i][j]=1001;
for(int i=1,x,y,t;i<=n;i++)
{
read(x);read(y);read(t);
a[x][y]=min(a[x][y],t);
for(int j=0;j<=3;j++)
{
int tx=x+dx[j],ty=y+dy[j];
if(tx>=0&&ty>=0)a[tx][ty]=min(a[tx][ty],t);
}
}
bfs();
return 0;
}