数组的每个下标作为一个阶梯,第 i
个阶梯对应着一个非负数的体力花费值 cost[i]
(下标从 0
开始)。
每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。
请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0
或 1
的元素作为初始阶梯。
示例 1:
输入:cost = [10, 15, 20]
输出:15
解释:最低花费是从 cost[1] 开始,然后走两步即可到阶梯顶,一共花费 15 。
示例 2:
输入:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
输出:6
解释:最低花费方式是从 cost[0] 开始,逐个经过那些 1 ,跳过 cost[3] ,一共花费 6 。
提示:
cost
的长度范围是[2, 1000]
。cost[i]
将会是一个整型数据,范围为[0, 999]
。
思路
这是一个比较简单的DP题目,首先分析:
所谓的楼梯顶部在本题中指的应该是cost[cost.length]
这个位置(实际取不到,就是最后一个元素的下一个位置),并且每次都可以爬1
步或者爬2
步。
因此,从递推(递归的话是从原问题开始,逐步分解成子问题。而递推是从子问题开始,逐步组合成原问题)的角度来看,不放设dp[x]
为走到x
处所要花费的最小体力,那么dp[0]
和dp[1]
是已知的(因为可以选择从0
或1
开始爬楼梯)。
接下来考虑状态转移方程:每次都可以爬1
步或者2
步可以看做是一个二叉的决策过程,比如,在示例2
中,位于cost[0]=1
处时,可以选择去cost[1]=100
处,也可以选择去cost[2]=1
处,其他地方同理。因此,就不难得出:
dp[x] = min(dp[x-1], dp[x-2])+cost[x]
也即:走到x
处所要花费的最小体力,无非是由前一步的最优情况时,再爬1
步楼梯或者爬2
步楼梯而来,同时再加上自己本身的花费cost[x]
,就构成了dp[x]
。(注:cost[cost.length]
应为0,因为此时已经到顶部,无需再花费体力)
至此,将思路转化为代码,答案就出来啦~
代码
public class Solution {
int[] dp = new int[1010];
public int walk(int[] cost) {
dp[0] = cost[0];
dp[1] = cost[1];
for(int i=2;i<cost.length;i++) {
dp[i] = Math.min(dp[i-1], dp[i-2]) + cost[i];
}
dp[cost.length] = Math.min(dp[cost.length-1], dp[cost.length-2]);
return dp[cost.length];
}
public int minCostClimbingStairs(int[] cost) {
return walk(cost);
}
}