描述
小A在玩一个游戏,有N个格子,每个格子上有个对应的Ki,代表在第i格的时候只能前进或者后退Ki格。小A目前在第Q格,那么,小A至少需要移动几次才能到达第P格呢?
当然,小A无法到达除1到N外的其他格子。例如:3,3,1,2,5代表Ki,从第1格开始。在第1格,前进K1到达第4格,由于1-3=-2不在1到N中,所以选择不能后退K1.。
输入
共两行。
第一行为三个用空格隔开的正整数,表示N,Q,P
第二行为N个用空格隔开的非负整数,表示Ki。
输出
一行,即最少移动次数,若无法到达,则输出-1。
输入样例 1
5 1 5
3 3 1 2 5
输出样例 1
3
提示
1≤N≤200,1≤Q,P≤N
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
// 计算到达目标位置P的最少移动次数
int minMovesToReachP(int N, int Q, int P, vector<int>& Ki) {
// 使用BFS算法,使用队列存储待访问的位置
// visited数组用于标记已经访问过的位置
vector<bool> visited(N + 1, false);
queue<pair<int, int>> q; // 存储位置和移动次数
q.push({Q, 0}); // 将起始位置Q和移动次数0加入队列
visited[Q] = true; // 标记起始位置为已访问
while (!q.empty()) { // 当队列不为空时循环
int currentPos = q.front().first; // 获取当前位置
int moves = q.front().second; // 获取移动次数
q.pop(); // 弹出队首元素
if (currentPos == P) { // 如果当前位置为目标位置P,返回移动次数
return moves;
}
// 计算前进和后退的位置
int forwardPos = currentPos + Ki[currentPos - 1];
int backwardPos = currentPos - Ki[currentPos - 1];
// 检查前进位置是否在范围内且未被访问过,是则加入队列并标记为已访问
if (forwardPos >= 1 && forwardPos <= N && !visited[forwardPos]) {
q.push({forwardPos, moves + 1});
visited[forwardPos] = true;
}
// 检查后退位置是否在范围内且未被访问过,是则加入队列并标记为已访问
if (backwardPos >= 1 && backwardPos <= N && !visited[backwardPos]) {
q.push({backwardPos, moves + 1});
visited[backwardPos] = true;
}
}
return -1; // 无法到达目标位置P,返回-1
}
int main() {
int N, Q, P;
cin >> N >> Q >> P; // 输入N,Q,P
vector<int> Ki(N);
for (int i = 0; i < N; i++) {
cin >> Ki[i]; // 输入Ki数组
}
int result = minMovesToReachP(N, Q, P, Ki); // 调用函数计算最少移动次数
cout << result << endl; // 输出结果
return 0;
}