题目 : 链接: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;
}