问题描述
小D接到一项任务,要求他爬到一座n层大厦的顶端与神秘人物会面。这座大厦有一个神奇的特点,每层的高度都不一样,同时,小D也拥有一项特殊能力,可以一次向上跳跃一层或两层,但是这项能力无法连续使用。已知向上1高度消耗的时间为1,跳跃不消耗时间。由于事态紧急,小D想知道他最少需要多少时间到达顶层。
输入格式
第一行包含一个整数n,代表楼的高度。
接下来n行每行一个整数ai,代表i层的楼层高度(ai <= 100)。
输出格式
输出1行,包含一个整数,表示所需的最短时间。
样例输入
5
3
5
1
8
4
样例输出
1
数据规模和约定
对20%的数据,n<=10
对40%的数据,n<=100
对60%的数据,n<=5000
对100%的数据,n<=10000
思路:
本道题目涉及到动态规划,也就是说我们要如何正确的选择跳和爬才能使得花费的时间最小,我们知道跳跃完成后需要休息不能连续使用,而我们希望当跳跃完成后下一层楼的高度是1,或者是比前一层还要来得小的。就本例题进行分析:首先我们可以将第一层的高度作为需要爬一层楼的高度(也就是需要消耗的时间),从第二层开始进行循环,然后和当前跳的层数花费的时间进行比较,我们知道跳的层数是不需要花费时间的,而跳跃这个数组实际上存储的是前两次爬的花费时间的最优解,代入状态转移方程:
P[i] = min(T[i - 1], P[i - 1]) + arr[i]
我们就可以更新我们爬楼所用的时间了,紧接着我们在比较前两次爬楼的时间所花费的时间,小的就说明我们是跳到前面这层,而下一层不能跳了需要爬,而花费的时间就等于小的这个值。拿本题来举例,最后一次循环时,我们可以选跳到花费9个时间点的楼层的前面,也可以跳过这一层,然后爬只花费1个时间结点的这一层。最后只需要比较最后一次的跳跃的结果即可
完成代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] p = new int[10240]; //初始化值大,满足数模的要求
int[] t = new int[10240];
int[] arr = new int[10240];
int n = sc.nextInt();
for (int i = 1; i <= n; i++){
arr[i] =sc.nextInt(); //存入到数组中
}
p[1] = arr[1]; // 第一层所花费的时间先存入
for (int i = 2; i <=n; i++){
p[i] = Math.min(p[i-1],t[i-1]) + arr[i]; //第一层爬和第一层跳先比,更新下一层的数据
t[i] = Math.min(p[i-1],p[i-2]);// 比较前两层,取最小值,因为跳是不花费时间,于是t存的值实际上是前两次爬最优的解
}
System.out.println(Math.min(p[n],t[n]));
}
}
测试结果:
![](https://i-blog.csdnimg.cn/blog_migrate/c1efac64ef53da656c9b309cc4ed7364.png)