洛谷【P1135】奇怪的电梯 解题报告

【传送门】:http://www.luogu.org/problem/show?pid=1135

---------------------------------------------------题目----------------------------------------------------------

题目描述

    呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第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。

输入输出样例

输入样例#1:

LIFT.IN
5 1 5
3 3 1 2 5

输出样例#1:

LIFT.OUT
3

-------------------------------------------------解题过程--------------------------------------------------------

刚开始写的BFS 拿了80分,错了两个测试点,虽然那个PIN好像有点多余,但还是懒得删QAQ,

//初始代码(BFS版)
var
  head,tail:longint;  //对头对尾指针
  temp:longint;     
  i,n,a,b,sum:longint;  
  num:array[1..200] of longint;
  f:array[0..201] of record   //记录类型,data用于记录队列里的数,pin用于记录已经走了几次
                   data:longint;
                   pin:shortint;
                 end;
  boo:array[1..200] of boolean;
//-------------------------------------------------
procedure printf(uuu:longint);    //输出过程
begin
  writeln(f[uuu].pin);      halt;
end;
//-------------------------------------------------
begin
  readln(n,a,b);    
  for i:= 1 to n do read(num[i]);   //输出过程
  if a=b then begin                 //如果起点等于终点就输出0
              writeln(0);
              halt;
           end;
  sum:=n;               //sum用于记录剩余可走的层数
  head:=0;   tail:=1;    fillchar(boo,sizeof(boo),true);    //初始化
  f[1].data:=a;    f[1].pin:=0;   boo[1]:=false;    dec(sum);      //错误就在这一行   
//BFS开始--------------------------------------------------------------------                  
  while head<tail do
  begin
    inc(head);   
    temp:=f[head].data+num[f[head].data];    //往上走
    if (temp>=1) and (temp<=n) and (boo[temp]) then  
      begin
        if sum=0 then   begin   writeln(-1); halt;  end;     //这个有点鸡肋,不过懒得删
        inc(tail);     f[tail].data:=temp;     f[tail].pin:=f[head].pin+1;      
        boo[temp]:=false;       dec(sum);
        if temp=b then printf(tail);     //到达指定楼层就输出
      end;
    temp:=f[head].data-num[f[head].data];   //往下走
    if (temp>=1) and (temp<=n) and (boo[temp]) then  
      begin                                     //同上
        if sum=0 then   begin   writeln(-1); halt;  end;   
        inc(tail);    f[tail].data:=temp;       f[tail].pin:=f[head].pin+1; 
        boo[temp]:=false;       dec(sum);
        if temp=b then printf(tail);
      end;
  end;
//BFS结束--------------------------------------------------------------------
  writeln(-1);    //当BFS后发现没办法到达输出 -1
end.

       两个错的测试点,一个是因为我用了shortint(退shortint报平安~),还有一个是因为弄错了初始化的时候给boo布尔数组的赋值下标(详见第27行)

      正确的BFS版本如下:

//正确代码(BFS版)
var
  head,tail:longint;   //对头对尾指针
  temp:longint;
  i,n,a,b,sum:longint;
  num:array[1..200] of longint;
  f:array[0..201] of record  //记录类型,data用于记录队列里的数,pin用于记录已经走了几次
                        data:longint;
                        pin:integer;    //拒绝shortint,从我做起……
                      end;
  boo:array[1..200] of boolean;
//-------------------------------------------------
procedure printf(uuu:longint);  //输出过程
begin
  writeln(f[uuu].pin);      halt;
end;
//-------------------------------------------------
begin
  readln(n,a,b);
  for i:= 1 to n do read(num[i]);    //输出过程
  if a=b then begin          //如果起点等于终点就输出0
               writeln('0');
               halt;
           end;
  sum:=n;    //sum用于记录剩余可走的层数【鸡肋……】
  head:=0;   tail:=1;    fillchar(boo,sizeof(boo),true); 
  f[1].data:=a;    f[1].pin:=0;   boo[a]:=false;    dec(sum);     //已更正错误     
//BFS开始--------------------------------------------------------------------                  
  while head<tail do
  begin
    inc(head);
    temp:=f[head].data+num[f[head].data];    //往上走
    if (temp<=n) and (boo[temp]) then  
      begin  
        if sum=0 then   begin   writeln('-1');   halt;  end;     //这个有点鸡肋,不过懒得删
        inc(tail);     f[tail].data:=temp;     f[tail].pin:=f[head].pin+1;
        boo[temp]:=false;       dec(sum);
        if temp=b then printf(tail);          //到达指定楼层就输出
      end;
    temp:=f[head].data-num[f[head].data];   //往下走
    if (temp>0) and (boo[temp]) then  
      begin                               //同上
        if sum=0 then   begin   writeln('-1');   halt;  end;  
        inc(tail);    f[tail].data:=temp;       f[tail].pin:=f[head].pin+1; 
        boo[temp]:=false;       dec(sum);
        if temp=b then printf(tail);
      end;
  end;
//BFS结束--------------------------------------------------------------------
  writeln('-1');   //当BFS后发现没办法到达输出 -1
end.

  题目的标签是递推,但我只会用广搜……不过还是勉强AC了

 

 

===================================20170209=======================================

 

qwq猛然发现原来可以用Floyd,数据太水。。。。

我们初始化为maxlongint div 3,自己到自己就是0,读入时把 i 到它可以到的楼层之间的距离赋为1 就可以啦

然后Floyd裸题

 1 program lift;
 2 uses math;
 3 var
 4     i,j,k,tmp,t_o,n,a,b:longint;
 5     f:array[1..200,1..200] of longint;
 6 
 7 begin
 8     readln(n,a,b);
 9     for i:= 1 to n do
10       for j:= 1 to n do
11         if i<>j then f[i,j]:=maxlongint div 2; //初始化
12 
13     for i:= 1 to n do
14       begin
15          read(tmp);
16          t_o:=i+tmp;
17          if t_o<=n then f[i,t_o]:=1;
18          t_o:=i-tmp;
19          if t_o>0 then f[i,t_o]:=1;
20       end;
21 
22     for k:= 1 to n do
23       for i:= 1 to n do
24         for j:= 1 to n do
25           f[i,j]:=min(f[i,j],f[i,k]+f[k,j]);
26 
27     if f[a,n]<>maxlongint div 3 then writeln(f[a,n])
28       else writeln(-1);
29 end.

 

posted @ 2016-08-13 18:10  bobble  阅读(1886)  评论(0编辑  收藏  举报