问题描述
小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.0s 内存限制:256.0MB
解题思路:
这是一道算法设计题,核心思想是动态规划。这里需要指明,对于每一层都可能来自两种情况,一种是爬上来的,另一种是跳上来的,这里考虑使用一个列数为 2 的矩阵进行记录,至于行数的选择可以考虑到题目里给出跳一次可以是一层的距离也可以是两层的距离,故这里考虑到一般都是从第二层开始循环遍历,需要考虑来自连续跳跃两层的情况,故行数考虑设置为 层数 + 1,其中第 0 层用于给第二层的跳跃判断可以用,不会导致程序因为下标越界报错跳出。前面说到,对于每一层判断,到这一层之前是爬上来的还是跳上来的,这里需要指出,跳上来的话不能再跳一次,爬上来的话可以继续爬也可以选择跳,这也是题目给出的不能连续跳跃的意思。所以可以看到代码里面给出了一个 for 循环,循环体是两个语句,第一个语句表示我现在这一层选择爬上去,那么对于上一层是怎么过来的就没有约束,以为上一层可以是爬也可以是跳,也就是说可以连续两次爬,也可以跳完再爬;对于第二个语句的意思就是说我这一层选择跳着上去,那么对于上一层就有约束了,即上一层不能是跳的,只能是爬的,也就是题目给的不能连续两次跳跃的意思。该算法的 JAVA 代码实现如下:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int[] height = new int[n];
for (int i = 0; i < n; i++) {
height[i] = scan.nextInt();
}
int[][] dp = new int[n + 1][2];
/**
* dp[x][0] 表示爬上来
* dp[x][1] 表示跳上来
* 爬和跳通过第二索引 0/1 进行区分
*/
dp[1][0] = height[0];
dp[1][1] = 0;
/**
* 对每一层都考虑跳上来和爬上来
*/
for (int i = 2; i <= n; i++) {
dp[i][0] = Math.min(dp[i - 1][0], dp[i - 1][1]) + height[i - 1];
dp[i][1] = Math.min(dp[i - 1][0], dp[i - 2][0]);
}
System.out.println(Math.min(dp[n][0], dp[n][1]));
scan.close();
}
}