P3383: [Usaco2004 Open]Cave Cows 4 洞穴里的牛之四
这个系列总算是做完了,这是我第一次高效率做完四道题,虽然中间有两道水题,但是第一和第四题还是蛮好的,但是只要能想到思路就很快能打完的。
像这道题,刚开始在想能不能用DP?但是苦于不知道怎么实施,后来又想,这么多点,有点像最短路径,但是总共有50000个点,边数有可能N*N吗?
于是我拿起笔算了一下,发现连边的话,先按X轴由小到大排序一遍,然后往后找 X 比当前点大 <=2 的 X,再通过比较 Y 之间的关系,只要相差不超过 2 就连接一条双向边,这样后面的点就不需要往前找了,但有人会问,会不会是 50001*25000 而超时呢?我也想过,但是发现根本不可能,因为一个点最多能连接24条边,儿往后最多能找到14个点,也就是时间最多也就 50000*14 而事实上,这也是根本不可能达到的。所以我们连好边后做一遍 spfa 就行了。
1 const maxn=50001;
2 type
3 node=record
4 f,t:longint;
5 end;
6 position=record
7 x,y:longint;
8 end;
9 var n,t,i,j,num,now,ans:longint;
10 b:array[0..750000] of node;
11 d,head:array[0..50001] of longint;
12 pos:array[0..50001] of position;
13 p:array[0..50001] of boolean;
14 f:array[0..5000000] of longint;
15 procedure qs(t,w:longint);
16 var l,r,mid:longint;
17 tem:position;
18 begin
19 l:=t; r:=w; mid:=pos[(l+r) shr 1].x;
20 repeat
21 begin
22 while pos[l].x<mid do inc(l);
23 while pos[r].x>mid do dec(r);
24 if l<=r then
25 begin
26 tem:=pos[l];
27 pos[l]:=pos[r];
28 pos[r]:=tem;
29 inc(l);
30 dec(r);
31 end;
32 end;
33 until l>r;
34 if t<r then qs(t,r);
35 if l<w then qs(l,w);
36 end;
37 procedure spfa;
38 var l,r,now,nowe:longint;
39 begin
40 fillchar(p,sizeof(p),true);
41 for l:=1 to n do d[l]:=maxn;
42 l:=1; r:=1; f[1]:=0; d[0]:=0; p[0]:=false;
43 while l<=r do
44 begin
45 now:=f[l];
46 nowe:=head[now];
47 while nowe<>0 do
48 begin
49 if d[now]+1<d[b[nowe].t] then
50 begin
51 d[b[nowe].t]:=d[now]+1;
52 if p[b[nowe].t] then
53 begin
54 p[b[nowe].t]:=false;
55 inc(r);
56 f[r]:=b[nowe].t;
57 end;
58 end;
59 nowe:=b[nowe].f;
60 end;
61 inc(l);
62 p[now]:=true;
63 end;
64 end;
65 procedure insert(f,t:longint);
66 begin
67 inc(num);
68 b[num].f:=head[f];
69 b[num].t:=t;
70 head[f]:=num;
71 end;
72 begin
73 readln(n,t);
74 for i:=1 to n do
75 with pos[i] do readln(x,y);
76 qs(1,n);
77 pos[0].x:=0; pos[0].y:=0;
78 for i:=0 to n-1 do
79 begin
80 now:=i+1;
81 while (pos[now].x-pos[i].x<=2) and (now<=n) do
82 begin
83 if abs(pos[now].y-pos[i].y)<=2 then
84 begin
85 insert(i,now);
86 insert(now,i);
87 end;
88 inc(now);
89 end;
90 end;
91 spfa;
92 ans:=maxn;
93 for i:=1 to n do
94 if (ans>d[i]) and (pos[i].y=t) then ans:=d[i];
95 if ans<>maxn then writeln(ans)
96 else writeln(-1);
97 end.
(转载请注明出处:http://www.cnblogs.com/Kalenda/)