• 洛谷【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.
  • 相关阅读:
    函数 free 的原型
    malloc 返回值的类型是 void *
    malloc 函数本身并不识别要申请的内存是什么类型
    用 free 或 delete 释放了内存之后,立即将指针设置为 NULL,防止产 生“野指针”
    动态内存的申请与释放必须配对,防止内存泄漏
    避免数组或指针的下标越界,特别要当心发生“多 1”或者“少 1” 操作
    不要忘记为数组和动态内存赋初值
    用 malloc 或 new 申请内存之后,应该立即检查指针值是否为 NULL
    释放了内存却继续使用它
    忘记了释放内存,造成内存泄露
  • 原文地址:https://www.cnblogs.com/bobble/p/5768516.html
Copyright © 2020-2023  润新知