奇怪的电梯
(原题连接:权限限制没有链接)
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?
输入
输入文件共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),第二行为N个用空格隔开的正整数,表示Ki。
输出
输出文件仅一行,即最少按键次数,若无法到达,则输出-1。
样例
LIFT.IN
5 1 5
3 3 1 2 5
LIFT.OUT
3
个人解法:
这是一个比较easy的题了。其实我在考场上想的的跑最短路,对于每一层,对于它可以到达的楼层建一条边。之后dijkstral一趟求答案。
我还可以再蒟蒻一点吗?
虽然这一波数据e<=400,n<=200,最短路是很简单的。SPFA大概跑个O(e),dijkstral的O(n^2)都可以轻松过,都不至于加一个堆优化。
显然还是有更优的算法的。
毕竟每一个建了一个图之后,要求的是边权为1的最短路,倒不如O(n)的BFS跑得快。所以可以直接O(n)跑BFS遍历这张图。
然而考场上蒟蒻的我只想出了dijkstral。而且!dijkstral还打错了……导致丢了10分。诶
代码如下(dijkstral):
var
k,dist:array[1..201] of longint;
w:array[1..201,1..201] of longint;
flag:array[1..201] of boolean;
n,i,j,s,t:longint;
procedure dijkstral(i:longint);//dijkstral跑最短路
var
vi,vj,minn,p:longint;
begin
flag[i]:=true;
for vi:=1 to n do
dist[vi]:=w[i,vi];
for vi:=1 to n-1 do
begin
minn:=400;
for vj:=1 to n do
if not flag[vj] and (dist[vj]<=minn) then//显然如果写dist[vj]<minn就bomb了。这样一来p不会赋值,可能在第一次寻找p的时候就找不到(边权相同的情况)一个最小的p来更新minn。然后就愉悦地被卡掉了。
begin
minn:=dist[vj];
p:=vj;
end;
flag[p]:=true;
for vj:=1 to n do
if dist[vj]>dist[p]+w[p,vj] then dist[vj]:=dist[p]+w[p,vj];
end;
end;
begin
read(n,s,t);
for i:=1 to n do
read(k[i]);
for i:=1 to n do
begin
if i+k[i]<=n then w[i,i+k[i]]:=1;
if i-k[i]>=1 then w[i,i-k[i]]:=1;//读入与建图
end;
for i:=1 to n do
for j:=1 to n do
if w[i,j]=0 then w[i,j]:=400;
for i:=1 to n do
w[i,i]:=0;
dijkstral(s);//跑一趟最短路
if dist[t]<>400 then writeln(dist[t])//输出
else writeln('-1');
end.
我还说什么好?我已经简直了……