奇怪的电梯(BFS)

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

输入格式:
共二行。
第一行为3个用空格隔开的正整数,表示N,A,B(1≤N≤200,1≤A,B≤N)。
第二行为N个用空格隔开的非负整数,表示Ki 。
输出格式:
一行,即最少按键次数,若无法到达,则输出−1。
样例.in
5 1 5
3 3 1 2 5
样例.out
3

题目分析
感觉好像和之前做过的某OJ的题目很像,是这题:
https://blog.csdn.net/c_uizrp_dzjopkl/article/details/82186601

大体的框架是一样的(毕竟都是BFS呀),但是我们要注意一下对边界条件的控制,和现在加那一层
具体的看我的代码吧 :-)

代码

#include <bits/stdc++.h>
using namespace std;

struct node
{
    int now;   //目前层数 
    //本来想加一个step计算要加那一层了,但是仔细的想一下子,当前要加上的层数不就是a[q.now]吗?
    //(a是用来存每一层可进行操作的楼数的)
    int cnt;    //计数器
}q,p;       //q是工具,p是实体

int vis[400010],n,x,y,a[200000];   /vis用来存那层去过(这样不会重复了)

int main()
{
    queue<node>line;       //建立队列

    cin>>n>>x>>y;          //输入
    for (int i = 1; i <= n; i++)
        cin>>a[i];

    memset(vis,0,sizeof(vis));          //初始化,所以层都没有去过
    p.now =  x;     //从第x层开始
    p.cnt = 0;      //当前没去过一层
//  p.step = 1;
    line.push(p);      //第一个状态压入队列
    vis[p.now] = 1;       //当前位置来过了,避免重复来到初始位置

    while (!line.empty())        //队列不空就循环
        {
            p = line.front();   //取出队首

            if (p.now == y)      //看一看有没有找到
                {
                    cout<<p.cnt;    //输出当前计数器
                    return 0;       //程序退出,完美结束 
                }

            p.cnt++;      //反之,继续找,加上层数加一(关于层数可以去看笔者上文链接的博客,有图欧(我手画的,丑的一批))

            if (p.now < y)          //对是否可以进行上升操作的判断
                {
                    q = p;             //给工具赋值
                    q.now += a[q.now];     //进行操作

                    if  (vis[q.now] == 0)        //判断这一层有没有来过
                        {                        //没来过
                            line.push(q);        //压入队列
                            vis[q.now] = 1;      //打标记
                        }       
                }        

            if (p.now - a[p.now] >= 1)     //判断能不能进行下降的操作(最底层是1楼,没有更低的了)
                {
                    q = p;            //给工具赋值
                    q.now -= a[q.now];     //进行操作

                    if (vis[q.now] == 0)          //操作的意义和上面的一样
                        {                 
                            line.push(q);
                            vis[q.now] = 1;
                        }
                }

            line.pop();       //摘掉用过的子父节点
        }
    //如果程序没有退出,并且尽可能的都搜完了,无解
    cout<<-1;      //输出
    return 0;      //又一次完美的结束:-)
}
                                       **蒟蒻新星c_uizrp_dzjopkl原创**

猜你喜欢

转载自blog.csdn.net/c_uizrp_dzjopkl/article/details/82261283