bfs——Meteor Shower S
P2895 [USACO08FEB]Meteor Shower S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
主要把握两个方面。
1.用一个二维数组mapp来记录每个格子最早遭受流星的时间点,这样在走迷宫的时候就可以用来判断能否走这个格子
(用当前时间与mapp中记录的时间进行比大小,从而判断能否走这个格子)
2.用一个二维数组num来记录人到达每个格子的时间,求得最后答案
自己的问题:
看到题目觉得复杂,没有深入思考。其实这道题就是bfs,只不过判断条件是当前时间能否走这个格子。
注意抓住key,想要判断当前时间能否走这个格子,就应该求每个格子被破坏的最早时间,那就是在输入流星坐标时,记录该坐标以及附近坐标遭受流星的时间点。然后在bfs中作为移动的判断条件。
注意终止条件是找到安全地或者找遍整个地图仍然找不到安全地。找到的安全地应该是mapp初始化为-1的地方或者是超过x、y范围的地方(坐标不可以是负数),找不到就是遍历完所有坐标后直接输出-1,返回。
1 #include <bits/stdc++.h>
2 using namespace std;
3 const int N=350;
4 int n,mapp[N][N],sx,sy,stime,num[N][N];
5 int dx[5]={0,0,0,1,-1},dy[5]={0,1,-1,0,0};
6 bool st[N][N];
7 //n为流星个数,mapp记录每个格子最早遭受流星的时间点
8 //sx、sy、stime为每个流星坐标与时间
9 //num为那个人走到(x、y)时需要的时间
10 //st判断是否走过了这个坐标
11
12 typedef pair<int,int> pii;
13 queue<pii> q;
14 void bfs()
15 {
16 q.push({0,0}); //把原点放进去
17 st[0][0]=1; //表示已走过
18 while(!q.empty())
19 {
20 pii sta=q.front(); q.pop();
21 int x=sta.first,y=sta.second;
22 if(mapp[x][y]==-1||x>300||y>300)
23 {
24 printf("%d\n",num[x][y]);
25 return;
26 }
27 int s=num[x][y]+1; //(x,y)再移动一步
28 for(int i=1;i<=4;i++)
29 {
30 int xx=x+dx[i],yy=y+dy[i];
31 if(xx>=0&&yy>=0&&!st[xx][yy]&&(mapp[xx][yy]>s||mapp[xx][yy]==-1))
32 {
33 st[xx][yy]=1;
34 q.push({xx,yy});
35 num[xx][yy]=num[x][y]+1;
36 }
37 }
38 }
39
40 printf("-1\n");
41 return;
42
43
44 }
45 int main()
46 {
47 scanf("%d",&n);
48 memset(mapp,-1,sizeof mapp);//使每个格子最早遭遇流星的时间点初始化为-1
49 //等所有流星记录完后如果某个坐标的mapp还是-1,说明没受到流星攻击,安全地
50
51 for(int i=1;i<=n;i++)
52 {
53 scanf("%d%d%d",&sx,&sy,&stime);
54 for(int j=0;j<5;j++)
55 {
56 int sxx=sx+dx[j],syy=sy+dy[j];
57 if(sxx>=0&&syy>=0&&(mapp[sxx][syy]==-1||mapp[sxx][syy]>stime))
58 //如果移动后的坐标在范围内
59 //并且没有没标记时间或者标记的时间大于该流星到达的时间
60 mapp[sxx][syy]=stime;
61 }
62 }
63
64 bfs();
65
66
67
68 return 0;
69 }