题意
天上落下m个陨石,第i个陨石落在(x,y)位置,掉落时刻为t。掉落之后这个点和其相邻的四个点就不能走了,问一个人能不能到达安全区域,如果能到达,最短需要多少时间?
题解
BFS搜索即可,首先记录一下最早落在某个点的陨石的下落时间。如果BFS到某个点,这个点截止到下一刻,都不会出现陨石的话,就可以把这个点加入队列。如果队列为空时还未到达安全点,则代表无法到达安全点,输出-1。
注意事项
这道题有很多坑,比如说陨石掉落是在[0,300]之间,但是影响范围却持续到301。这个问题的话,一般来说数组开大点就能避免。
还有一个问题是代码编写上的问题,在判断初始掉落时间的时候,应该为
stones[x+dir[i][0]][y+dir[i][1]]=min(stones[x+dir[i][0]][y+dir[i][1]],t);
但是,不慎写成了
stones[x+dir[i][0]][y+dir[i][1]]=min(stones[x][y],t);
然后就导致有多组样例过不了。。。。。
调试心得
在调试过程中,为了看路径,用到了链表。不过表示C++链表真心不好用,各种指针规则,ORZ。。把调试代码放出来,供大家参考吧。需要特别注意的是,如果把调试代码交上去会TLE。。(大概是因为内存分配很耗时间吧)
调试代码
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<string>
#define INF 1e9
using namespace std;
int w,h;
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
bool unsafe[550][550];
struct Node{
int x,y,t;
struct Node *father;
};
int stones[550][550];
int bfs(Node nd){
queue<Node*> que;
que.push(&nd);
while(!que.empty()){
Node* front=que.front();
que.pop();
if(!unsafe[front->x][front->y]){
cout<<front->x<<" "<<front->y<<endl;
Node* d=front->father;
while(d!=nullptr){
cout<<d->x<<" "<<d->y<<" "<<d->t<<endl;
d=d->father;
}
return front->t;
}
for(int i=0;i<4;i++){
Node* newNode=new Node;
newNode->x=front->x;
newNode->y=front->y;
newNode->x+=dir[i][0];
newNode->y+=dir[i][1];
if(newNode->x<0||newNode->y<0)
continue;
if(stones[newNode->x][newNode->y]<=(front->t+1)){
continue;
}
newNode->father=front;
newNode->t=(front->t+1);
que.push(newNode);
}
}
return -1;
}
int main()
{
int n;
while(~scanf("%d",&n)){
memset(unsafe,false,sizeof(unsafe));
for(int i=0;i<350;i++){
for(int j=0;j<350;j++){
stones[i][j]=INF;
}
}
Node* nd=new Node;
for(int i=0;i<n;i++){
int x,y,t;
scanf("%d%d%d",&x,&y,&t);
unsafe[x][y]=true;
stones[x][y]=min(stones[x][y],t);
for(int i=0;i<4;i++){
if((x+dir[i][0])<0||(y+dir[i][1])<0)
continue;
unsafe[x+dir[i][0]][y+dir[i][1]]=true;
stones[x+dir[i][0]][y+dir[i][1]]=min(stones[x+dir[i][0]][y+dir[i][1]],t);
}
}
nd->x=0;
nd->y=0;
nd->t=0;
nd->father=nullptr;
printf("%d\n",bfs(*nd));
}
return 0;
}
AC代码
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<string>
#define INF 1e9
using namespace std;
int w,h;
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
bool unsafe[550][550];
bool used[550][550];
struct Node{
int x,y,t;
};
int stones[550][550];
int bfs(Node nd){
queue<Node> que;
que.push(nd);
while(!que.empty()){
Node front=que.front();
que.pop();
if(!unsafe[front.x][front.y]){
return front.t;
}
for(int i=0;i<4;i++){
Node newNode;
newNode.x=front.x;
newNode.y=front.y;
newNode.x+=dir[i][0];
newNode.y+=dir[i][1];
if(newNode.x<0||newNode.y<0)
continue;
if(stones[newNode.x][newNode.y]<=(front.t+1)){
continue;
}
if(used[newNode.x][newNode.y])
continue;
used[newNode.x][newNode.y]=true;
newNode.t=(front.t+1);
que.push(newNode);
}
}
return -1;
}
int main()
{
int n;
while(~scanf("%d",&n)){
memset(used,false,sizeof(used));
memset(unsafe,false,sizeof(unsafe));
for(int i=0;i<350;i++){
for(int j=0;j<350;j++){
stones[i][j]=INF;
}
}
Node nd;
for(int i=0;i<n;i++){
int x,y,t;
scanf("%d%d%d",&x,&y,&t);
unsafe[x][y]=true;
stones[x][y]=min(stones[x][y],t);
for(int i=0;i<4;i++){
if((x+dir[i][0])<0||(y+dir[i][1])<0)
continue;
unsafe[x+dir[i][0]][y+dir[i][1]]=true;
stones[x+dir[i][0]][y+dir[i][1]]=min(stones[x+dir[i][0]][y+dir[i][1]],t);
}
}
nd.x=0;
nd.y=0;
nd.t=0;
printf("%d\n",bfs(nd));
}
return 0;
}