Description
有一个奇怪的电梯,它可以停在任何一层楼,并且在每一层楼上有一个数字Xi 。 这个电梯只有两个按钮:UP 和 DOWN。 当你在第 i 层楼的时候,如果你按 UP ,那么你将上升 Xi 层楼(即是说你将到达第 i+Xi 层楼), 如果你按 DOWN,那么你将下降 Xi 层楼(即是说你将到达第 i-Xi 层楼)。 当然,你最多到达第 N 层楼,至少到达第 1 层楼。 例如,有一个5层楼的建筑,并且X1=3,X2=3, X3=1, X4=2, X5=5。 假如最开始你在第 1 层楼,那么此时如果你按 UP 的话,你将到达第4层楼(X1=3,1+3==4), 但是此时如果你按 DOWN 的话,则电梯不能操作,因为你不能到达 -2 层楼(X1=3,1-3 == -2)。 现在的任务是:假如你在第 A 层楼,你想去第 B 层楼,那么你至少需要按几次按钮(UP 或 DOWN)??
Input
多组输入 第一行输入三个数N,A,B (2 <= N,A,B <= 1000) 当 N==0时,输入结束。 第二行输入 N 个非负整数(即是题目描述中的Xi)。
Output
若能从A 到达B,则输出最少的按键数,否则输出 -1
Sample Input
5 1 5 3 3 1 2 5 2 1 2 55 6666 0
Sample Output
3 -1
这道题目是BFS【宽度优先搜索】里面很经典的题目,运用到了使用队列来进行宽搜的技巧。
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int lift[1005];
bool vis[1005];
int A, B, N;
struct node
{
int step, floor;
};
int BFS()
{
node cur, tmp_up, tmp_down;
cur.step = 0;
cur.floor = A;
queue<node> Q;
Q.push(cur);
vis[A] = true;
while (!Q.empty())
{
cur = Q.front();
Q.pop();
if (cur.floor == B)
return cur.step;
tmp_up.floor = cur.floor + lift[cur.floor];
if (vis[tmp_up.floor] == false && tmp_up.floor <= N && tmp_up.floor >= 1)
{
tmp_up.step = cur.step + 1;
Q.push(tmp_up);
vis[tmp_up.floor] = true;
}
tmp_down.floor = cur.floor - lift[cur.floor];
if (vis[tmp_down.floor] == false && tmp_down.floor >= 1 && tmp_down.floor <= N)
{
tmp_down.step = cur.step + 1;
Q.push(tmp_down);
vis[tmp_down.floor] = true;
}
}
return -1;
}
int main()
{
while (scanf("%d", &N) != EOF)
{
if (N == 0) break;
scanf("%d%d", &A, &B);
for (int i = 1; i <= N; ++i)
scanf("%d", &lift[i]);
memset(vis, false, sizeof(vis));
printf("%d\n", BFS());
}
return 0;
}