问题描述
有一个奇怪的电梯。电梯可以随心所欲地停在每个楼层,每个楼层都有一个数字Ki(0 <= Ki <= N)。电梯只有两个按钮:向上和向下。当你在第i层,如果按“UP”按钮,您将上Ki层,即您将进入第i+Ki层,同理,如果您按“DOWN”按钮,您将下降Ki 楼,即你会去 i-Ki 楼。当然,电梯不能上高于N,下也不能低于1。比如有5层楼,k1=3,k2=3,k3=1,k4= 2、k5 = 5。从1楼开始按“UP”键,上到4楼,按“DOWN”键,电梯不能运行它,因为它不能下到-2楼,如你所知,
问题来了:当你在A楼,你想去B楼时,他至少要按“UP”或“DOWN”按钮多少次?
输入
输入由几个测试用例组成。,每个测试用例包含两行。
第一行包含三个整数 N ,A,B( 1 <= N,A,B <= 200),如上所述,第二行包含 N 个整数 k1,k2,…kn。
单个 0 表示输入结束。
输出
对于输入输出一个整数的每一种情况,当你在A楼,你想去B楼时,你最少需要按下按钮的次数。如果你不能到达B楼,printf“-1”。
样本输入
5 1 5
3 3 1 2 5
0
样本输出
3
初始状态: (起始点,0)
终止状体:(终点, 0)
状态转移图:
#include<bits/stdc++.h>
using namespace std;
int n, a, b, k[205], vis[205]; // k:存放每个楼层的按钮,vis标记是否到达过某个楼层
struct node{
int level; // 层数1~n
int step; // 步数: 按的次数
};
void bfs() {
queue<node> q; // 注意这里的队列的是数据类型是结构体
node cur, next; // cur:当前状态, next: 下一层楼的状态
cur.level = a; // 初始化层为起始楼层
cur.step = 0; // 初始化步数为0
q.push(cur); // 将当前状态放入队列中
while(!q.empty()) { // 判断队列是否为空 == 遍历了所有可能的状态
cur = q.front(); // 取出对头元素为当前状态
q.pop(); // 弹出对头元素
if(cur.level == b) { // 判断是否到达终点
printf("%d\n", cur.step);
return ;
}
//向上
next.level = cur.level + k[cur.level]; // 下一个的楼层数
next.step = cur.step + 1; // 步数在cur的状态下加一
if(next.level <= n) { // 向上的楼层是否会超过输入的楼高
if(!vis[next.level]) { // 是否有到达过
q.push(next); //放入队列
vis[next.level] = 1; //标记到达过
}
}
//向下
next.level = cur.level - k[cur.level];
next.step = cur.step + 1;
if(next.level > 0) {
if(!vis[next.level]) {
q.push(next);
vis[next.level] = 1;
}
}
}
//遍历了所有结果都没有在while循环中退出说明没有一种可能能够到达
printf("-1\n");
return ;
}
int main() {
while(scanf("%d", &n), n) {
memset(vis, 0, sizeof(vis));
scanf("%d %d", &a, &b);
//因为楼层是从1~n,所以for循环中i从1开始到n取等
for(int i = 1; i <= n; i++) scanf("%d", &k[i]);
bfs();
}
return 0;
}