流星雨(BFS)

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

posted @ 2024-12-26 19:32  Marinaco  阅读(22)  评论(0)    收藏  举报
//雪花飘落效果