题目 : 链接:https://vjudge.net/problem/POJ-3669
题意:流星雨来袭,一共有m颗陨石,每颗ti时间点的陨石砸击(xi,yi)以及其上下左右共5个点,在砸击的时刻及砸击后人都不能踏上这个点。在第一象限内,人位于原点(0,0),每次可以上下左右移动一次,找到达到安全位置的最短时间
思路:开一张数表maze初始化所有元素为inf,然后在maze标记每个格子被陨石影响的最初时间点。
人从(0,0)开始bfs,若遇到maze[nx][ny]为inf即为结束状态,输出此时的时间,否则,比较此时时刻t加上1与maze[nx][ny]的大小,若t+1更小说明能够踏上nx,ny的点,把这个点放入队列
注意:
初始原点位置:如果maze[0][0]=0说明直接被砸死,直接return,不能将其放入队列中
数组越界问题:这道题目要求陨石落下位置xi,yi是>=0并且<=300的 然而安全位置的x,y可以超过300
同样的bfs中,上下左右移动时也要判断nx,ny是否越界
避免重复将某个点放入队列,可以将这个点大小更新为t+1,这样一来以后(t+1)+1>t+1 不会再回去了(用bool数组应该也行
建议:
结构体还是写得简洁一点比较好orz
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
const int inf = 1e5;
int m;
int dx[]={0,0,0,-1,1};
int dy[]={0,1,-1,0,0};
struct meteor{
int x;
int y;
int t;
};
struct now{
int x;
int y;
int t;
};
now pos;
queue<now>q;
int maze[305][305];
int bfs()
{
if(maze[0][0]==0)
{
return -1;
}
q.push({0,0,0});
while(!q.empty())
{
pos=q.front();
if(maze[pos.x][pos.y]==inf)return pos.t;
q.pop();
for(int i=1;i<=4;i++)
{
int nx=pos.x+dx[i];
int ny=pos.y+dy[i];
if(nx>=0&&ny>=0&&pos.t+1<maze[nx][ny])
{
if(maze[nx][ny]==inf)return pos.t+1;
else{
maze[nx][ny]=pos.t+1;
}
q.push({nx,ny,pos.t+1});
}
}
}
return -1;
}
signed main()
{
scanf("%d",&m);
for(int i=0;i<=304;i++)
{
for(int j=0;j<=304;j++)
{
maze[i][j]=inf;
}
}
for(int i=1;i<=m;i++)
{
int x,y,t;
scanf("%d%d%d",&x,&y,&t);
for(int j=0;j<=4;j++)
{
if(x+dx[j]>=0&&y+dy[j]>=0&&x+dx[j]<=300&&y+dy[j]<=300)maze[x+dx[j]][y+dy[j]]=min(t,maze[x+dx[j]][y+dy[j]]);
}
}
cout<<bfs()<<endl;
return 0;
}
标签:int,pos,BFS,ny,&&,maze,inf,流星雨
From: https://www.cnblogs.com/benscode/p/18634066