师兄参加了华为的实习生招聘,我也蹭了一下热闹。
一、题目描述
给出一组正整数,你从第一个数向最后一个数方向跳跃,每次至少跳跃1格,每个数的值表示你从这个位置可以跳跃的最大长度。计算如何以最少的跳跃次数跳到最后一个数。
输入描述
第一行表示有多少个数n
第二行开始依次是1到n个数,一个数一行
输出描述
输出一行,表示最少跳跃次数。
示例1
输入
7
2
3
2
1
2
1
5
输出
3
说明
7表示接下来要输入7个正整数,从2开始。数字本身代表可以跳跃的最大步长,此时有2种跳法,为2-2-2-5和2-3-2-5都为3步。
二、分析
一开始看到这题就觉得难受,好麻烦的题目,师兄和我说是用动态规划做,要写出迭代方程什么的。
仔细想过之后,想起运筹学中确实是这么解这一类题的,不过那是把方案一起解出来了——也就是题中的“2-2-2-5和2-3-2-5”。可是题目要求的答案只是“最少跳跃次数”,并没有说要给出方案,说明还是可以取巧的。
先整理一下规律,假设第i步到达了第k个位置(从0开始编号),那么前面所有的位置应该都能在第i步或第i步之前到达,在下图中标为橙色。
下面开始走一边用例。第0步,此时能到达的点就是起点,所以也就第一个点被标记。同时可以计算出下一step能到达的最远位置为2(第一个格子的位置0 + 该格中的数字2),也就是从左到右数第3个格子,接下来把能到达的格子涂色。
更进一步。在橙色区域循环,计算出下一步最远能到达的点,第二个格子和第三个格子都符合要求,继续把能到达的格子标为橙色。
那么什么时候可以停止循环呢?很简单,只要最后一个格子变成橙色就结束循环了,也就是STEP_max >= n-1。
当然,当step=3时,就得到想要的结果了,此时也知道了最少需要跳跃3次才能到达终点。
以上的式子都是基于从0编号这一条件的,所以编程时我也从0开始编号。
三、解答
就直接贴上代码啦
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 先读入数据
int len = 0;
cin >> len;
vector<int> data(len);
for (int i = 0; i < len;i++) {
cin >> data[i];
}
// 循环,当到达末尾时跳出循环
int step = 0;
int out = 0;
int step_max = 0;
while (true) {
step++;
for (int j = 0; j <= out; j++) {
if (data[j] + j > step_max) {
step_max = data[j] + j;
}
}
out = step_max;
if (out + 1 >= len) {
break;
}
}
// 输出结果
cout << step << endl;
system("pause");
return 0;
}
转载请注明出处,谢绝盈利性质的转载。