题面(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原创**