题目描述
一只袋鼠要从河这边跳到河对岸,河很宽,但是河中间打了很多桩子,每隔一米就有一个,每个桩子上都有一个弹簧,袋鼠跳到弹簧上就可以跳的更远。每个弹簧力量不同,用一个数字代表它的力量,如果弹簧力量为5,就代表袋鼠下一跳最多能够跳5米,如果为0,就会陷进去无法继续跳跃。河流一共N米宽,袋鼠初始位置就在第一个弹簧上面,要跳到最后一个弹簧之后就算过河了,给定每个弹簧的力量,求袋鼠最少需要多少跳能够到达对岸。如果无法到达输出-1
输入描述:
输入分两行,第一行是数组长度N (1 ≤ N ≤ 10000),第二行是每一项的值,用空格分隔。
输出描述:
输出最少的跳数,无法到达输出-1
示例1
输入
5 2 0 1 1 1
输出
4
分析
这道题是典型的动态规划问题,用一个表格来分析。分析顺序为到第1个桩子时,最少需要多少步,到第2个桩子时,最少需要多少步,...到第n个桩子时,至少需要多少步。第n个桩子的最少步数与前面几个相关,同样第n-1个桩子的最少步数与前面步数也相关,....到第2个桩子的步数与第1个桩子的最少步数相关,而第1个桩子的步数一定为1。
步骤 | 柱子/相应可跳长度 | ||||
2 | 0 | 1 | 1 | 1 | |
a | b | c | d | e | |
第一步 | 1 | ||||
第二步 | 1 | 2 | |||
第三步 | 1 | 2 | 2 | ||
第四步 | 1 | 2 | 2 | 3 | |
第五步 | 1 | 2 | 3 | 3 | 4 |
如表所示,柱子用abcde来表示,相应可跳长度分别为2、0、1、1、1。
跳a桩时,总的最少用1步。
跳b桩时,只能从a跳到b,用1步,总的最少用2步(开始-a-b)。
跳c桩时,可以从a跳,可以从b跳。从a跳时,跳的长度可以达到c,故用1步;从b跳时,发现跳的长度为0,跳不到;故总的最少用2步(开始-a-c)。
跳d桩时,可以从a跳,从b跳,从c跳。从a和b跳发现跳不到d;所以只能从c跳到d,故总的最少用3(开始-a-c-d)。
跳e桩时,可以从a、b、c、d跳。从a、b、c跳发现跳不到e;所以只能从d跳到e,故总的最少用4(开始-a-c-d-e)。
动态规划问题的两个基本元素凑齐了,一个是递归基,一个是递归过程,其中是到第n个桩子时最少步数,为达到从第n-1个桩子到第n个桩子时需要的步数。
代码
package com.june.java;
public class DaiShu {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n=5;
int[] dp = new int[n+1];
int[] nums = {2,0,1,1,1};
dp[0]=1;
for(int i=1; i<n+1; i++){
dp[i] = 10000;
}
for(int i=1; i<=n; i++){
for(int j=i-1; j>=0; j--){
if(nums[j] == 0){
continue;
}
if(j+nums[j]>=i){
dp[i] = dp[i]<(dp[j]+1)?dp[i]:(dp[j]+1);
}
}
}
if(dp[n] == 10000){
System.out.println("-1");
}else{
System.out.println(dp[n]-1);
}
}
}