洛谷P1135信息奥赛一本通1360 奇怪的电梯(lift)

原题链接:

洛谷 https://www.luogu.com.cn/problem/P1135

信息奥赛一本通 http://ybt.ssoier.cn:8088/problem_show.php?pid=1360

题目:

1360:奇怪的电梯(lift)


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 4824     通过数: 2058

【题目描述】

大楼的每一层楼都可以停电梯,而且第i层楼1iN上有一个数字Ki(0≤=Ki≤=N。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了KiK1=3,K2=3,,从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有−2楼。那么,从A楼到B楼至少要按几次按钮呢?

【输入】

共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1N200,1A,BN),第二行为N个用空格隔开的正整数,表示Ki

【输出】

一行,即最少按键次数,若无法到达,则输出1

【输入样例】

5 1 5
3 3 1 2 5

【输出样例】

3



这是一道搜索题,这里可以运用广搜。
首先写一个队列a,h代表当前在几楼,C代表走了几步。
初始化就是先将初始楼层加入队列,
搜索过程就是讲队首元素取出,然后将在对首元素所在楼层按键后所能到达的楼层加入队尾,并且次数加一,如果到达指定楼层就输出次数,最后head++继续搜下一个,
循环条件就是队列非空,即head<=tail,
如果循环结束还没到达指定楼层就代表无法到达,输出-1。

代码:
c:
#include<stdio.h>
struct k{
    int h,c;//h代表当前在几楼,C代表走了几步
}a[201];//广搜队列 
int b[201];//存储数据 
int ye[201];//记录楼层是否到达 
int m,n,r,s;
int head,tail;
int main(){
    scanf("%d%d%d",&n,&r,&s);
    for(int i=1;i<=n;i++)scanf("%d",b+i);
    if(r==s){printf("0");return 0;}//如果初始楼层和目标楼层相同则不用走 
    a[0].h=r;a[0].c=0;// 初始楼层加入队列
    tail=head=0;
    while(head<=tail){//广搜 ,循环条件就是队列非空
        if(a[head].h+b[a[head].h]<=n&&ye[a[head].h+b[a[head].h]]==0){//向上走 
            ye[a[head].h+b[a[head].h]]=1;//记录该楼层已经走过 
            a[++tail].h=a[head].h+b[a[head].h];//楼层按键后所能到达的楼层加入队尾 
            a[tail].c=a[head].c+1;//并且次数加一
            if(a[tail].h==s){printf("%d",a[tail].c);return 0;}//如果到达指定楼层就输出次数
            }
        if(a[head].h-b[a[head].h]>=1&&ye[a[head].h-b[a[head].h]]==0){//向下走 
            ye[a[head].h-b[a[head].h]]=1;//记录该楼层已经走过 
            a[++tail].h=a[head].h-b[a[head].h];//楼层按键后所能到达的楼层加入队尾 
            a[tail].c=a[head].c+1;//并且次数加一
            if(a[tail].h==s){printf("%d",a[tail].c);return 0;}//如果到达指定楼层就输出次数
            }
    head++;//对首加1 
    }
    printf("-1");return 0;//如果循环结束还没到达指定楼层就代表无法到达,输出-1
}

pascal:

type k=record
    h:longint;
    c:longint;//h代表当前在几楼,C代表走了几步
end;
var
    a:array[0..200]of k;//广搜队列 
    b:array[1..200]of longint;//存储数据 
    ye:array[1..200]of boolean;//记录楼层是否到达 
    m:longint;
    n:longint;
    r:longint;
    s:longint;
    head:longint;
    tail:longint;
    i:longint;
begin
    read(n,r,s);
    for i:=1 to n do read(b[i]);
    if r=s then begin
        writeln(0);exit();//如果初始楼层和目标楼层相同则不用走
    end;
    a[0].h:=r;a[0].c:=0; // 初始楼层加入队列
    head:=0;tail:=head;
    while head<=tail do begin //广搜 ,循环条件就是队列非空
        if (a[head].h+b[a[head].h]<=n)and(ye[a[head].h+b[a[head].h]]=false)then begin //向上走
            ye[a[head].h+b[a[head].h]]:=true;//记录该楼层已经走过
            tail:=tail+1;
            a[tail].h:=a[head].h+b[a[head].h]; //楼层按键后所能到达的楼层加入队尾 
            a[tail].c:=a[head].c+1;//并且次数加一
            if a[tail].h=s then begin 
                writeln(a[tail].c);exit();//如果到达指定楼层就输出次数
            end;
        end;
        if (a[head].h-b[a[head].h]>=1)and(ye[a[head].h-b[a[head].h]]=false)then begin //向下走 
            ye[a[head].h-b[a[head].h]]:=true;//记录该楼层已经走过
            tail:=tail+1;
            a[tail].h:=a[head].h-b[a[head].h]; //楼层按键后所能到达的楼层加入队尾 
            a[tail].c:=a[head].c+1;//并且次数加一
            if a[tail].h=s then begin
                writeln(a[tail].c);exit();//如果到达指定楼层就输出次数
            end;
        end;
        head:=head+1;//对首加1 
    end;
    writeln(-1);//如果循环结束还没到达指定楼层就代表无法到达,输出-1
end.

我可能写的不好,如果有问题,请指出,谢谢。

原文地址:https://www.cnblogs.com/sy666/p/12403973.html