Rqnoj335 流星雨 题解

      又是搜索。这几天做了不少搜索题,对搜索题的脉络也有了一些新的理解。

      从我做的屈指可数的题目里面我发现,DFS的题相对于BFS来说更加灵活。比如“著名”的“24点”这道题,递归调用的方法很是神奇(或许我太弱小了…),而BFS的形式却相对单一,但是有时候却需要我们的一些灵活的思维(参见本Blog“无边界BFS处理办法”一文)。这道题就是运用灵活的思维处理BFS问题的又一例子。

 

【题目描述】(略改编自rqnoj335)
      Saltless听说有一场壮丽的流星雨即将来临,而且据说陨石将要落下来撞击地球并摧毁一切它遇到的东西。为了保证自己的安全,Saltless决定到一个安全的(永远不会被陨石击毁)地方去。
      报道表明将有M颗陨石落下(1 ≤ M ≤ 50,000),第i个陨石将在Ti(0 ≤ Ti ≤ 1,000)时刻砸中(Xi,Yi)点(0 ≤ Xi ≤ 300; 0 ≤ Yi ≤ 300) 。每颗陨石将击毁它直接砸中的点以及四个与其直接相邻的点。
      他现在所处的地方是坐标系的原点,并从零时刻起出发,前往一个安全的地点,要求是他经过某点时该点未被击毁。他只能在坐标系的第一象限以及x,y轴的正半轴上活动。
      求他能到达一个安全地点的最短时间。

【输入格式】
第一行:陨石个数M
第二行至第M+1行:第i+1行有三个整数表示:Xi,Yi,和Ti
数据范围见题目描述

【输出格式】
输出只有一行,即Saltless所需的最短时间。如果他永远无法到达一个安全的地方,输出-1

【样例输入】
4
0 0 2
2 1 2
1 1 2
0 3 5

【样例输出】
5

      这道题与传统BFS的不同在于,传统的BFS题中的障碍物(也就是本题中的陨石坑)是静止的,从一开始就在,不会消失。而这道题的障碍物却是“动态”的,并不是存在于整个过程。这就需要我们的一些“创新”的思维。

      我们知道,整个世界只有Saltless一个人,没有人为他填好陨石坑——也就是说,陨石坑一旦存在,就不会消失。所以,我们没有必要记录下每一块陨石撞击的时间,只用找到每个坐标最早被砸到的时间,在那个时间之前从那里经过就行了。

      我们用t数组记录点(i,j)不能走的最小时间,同时更新“四个与其直接相邻的点”的t值,然后在f数组中把会被砸到的点标记。这样,我们在BFS中一旦找到一个没有标记过的点,就可以输出步数,在那里悠闲地看流星雨啦~

      另外,注意题目中的描述,Saltless可以在坐标轴上走,而且地图的大小没有限制。所以301那一圈也要考虑。

 

      参考代码:

1 program meteor;
2 const
3 dx:array[1..4]of integer=(0,0,1,-1);
4 dy:array[1..4]of integer=(1,-1,0,0);
5 type l=record
6 x,y:longint;
7 dist:longint;
8 end;
9 var
10 i,j,k,n:longint;
11 fa,s:longint;
12 xx,yy,xt,yt:integer;
13 t:array[0..301,0..301]of longint;
14 v:array[0..301,0..301]of boolean;
15 f:array[0..301,0..301]of boolean;
16 d:array[1..100000]of l;
17 begin
18 assign(input,'metor.in');
19 reset(input);
20 assign(output,'metor.out');
21 rewrite(output);
22 readln(n);
23 fillchar(f,sizeof(f),false);
24 fillchar(v,sizeof(v),false);
25 for i:=1 to n do
26 begin
27 readln(xx,yy,k);
28 if(t[xx,yy]>k)or(t[xx,yy]=0)then //记录该点最短时间
29 begin
30 t[xx,yy]:=k;
31 f[xx,yy]:=true;
32 end;
33 for j:=1 to 4 do //更新相关四点最短时间
34 begin
35 xt:=xx+dx[j];
36 yt:=yy+dy[j];
37 if(xt>=0)and(xt<=301)and(yt<=301)and(yt>=0)then
38 if (t[xt,yt]>k)or(t[xt,yt]=0)then
39 begin
40 t[xt,yt]:=k;
41 f[xt,yt]:=true;
42 end;
43 end;
44 end;
45 fa:=1;
46 s:=1;
47 d[1].x:=0;
48 d[1].y:=0;
49 d[1].dist:=0;
50 v[0,0]:=true;
51 while fa<=s do
52 begin
53 for i:=1 to 4 do
54 begin
55 xx:=d[fa].x+dx[i];
56 yy:=d[fa].y+dy[i];
57 if(xx>=0)and(xx<=301)and(yy>=0)and(yy<=301)then
58 if not v[xx,yy]then
59 begin
60 if(f[xx,yy])and(t[xx,yy]>d[fa].dist+1)then
61 begin //如果会被砸到,判断当前时间该点是否可走,如果能走就记录下来
62 inc(s);
63 d[s].x:=xx;
64 d[s].y:=yy;
65 d[s].dist:=d[fa].dist+1;
66 v[xx,yy]:=true;
67 end;
68 if not f[xx,yy] then //如果安全,就直接输出
69 begin
70 writeln(d[fa].dist+1);
71 close(input);
72 close(output);
73 halt;
74 end;
75 end;
76 end;
77 inc(fa);
78 end;
79 writeln('-1');
80 close(input);
81 close(output);
82 end.

 

 

(Saltless原创,转载请注明出处)

posted on 2010-08-10 16:26  saltless  阅读(503)  评论(0编辑  收藏  举报

导航