37、46. 使用最小花费爬楼梯(动态规划就是后面状态由前面的状态决定)
给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例 1:
输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。
- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15 。
示例 2:
输入:cost = [1,100,1,1,1,100,1,1,100,1]
输出:6
解释:你将从下标为 0 的台阶开始。
- 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
- 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
- 支付 1 ,向上爬一个台阶,到达楼梯顶部。
总花费为 6 。
package com.example.lecode.DynamicProgramming;
/**
* 746. 使用最小花费爬楼梯(动态规划就是后面状态由前面的状态决定)
* 给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
*
* 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
*
* 请你计算并返回达到楼梯顶部的最低花费。
* 示例 1:
*
* 输入:cost = [10,15,20]
* 输出:15
* 解释:你将从下标为 1 的台阶开始。
* - 支付 15 ,向上爬两个台阶,到达楼梯顶部。
* 总花费为 15 。
* 示例 2:
*
* 输入:cost = [1,100,1,1,1,100,1,1,100,1]
* 输出:6
* 解释:你将从下标为 0 的台阶开始。
* - 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
* - 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
* - 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
* - 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
* - 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
* - 支付 1 ,向上爬一个台阶,到达楼梯顶部。
* 总花费为 6 。
*
* 对于动态规划问题,我将拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!
*
* 确定dp数组(dp table)以及下标的含义
* 确定递推公式
* dp数组如何初始化
* 确定遍历顺序
* 举例推导dp数组
*
*
*/
public class minCostClimbingStairs {
public static void main(String[] args) {
int[] cost = {1,100,1,1,1,100,1,1,100,1};
minCostClimbingStairs Solution = new minCostClimbingStairs();
int i = Solution.minCostClimbingStairs(cost);
System.out.println("楼梯顶部的最低花费:" + i);
}
public int minCostClimbingStairs(int[] cost) {
int len = cost.length;
// 为什么需要要给长度设置为len+1? 因为其中的我们在最开始放入两个初始值0(下标为0)和1(下标为1)的情况(也就是初始情况有两种)
int[] dep = new int[len+1];
// * dp数组如何初始化
dep[0] = 0;
dep[1] = 0;
for(int i = 2; i <= len; i++){
// * 确定递推公式
//dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。
//dp[i - 2] 跳到 dp[i] 需要花费 dp[i - 2] + cost[i - 2]。
//那么究竟是选从dp[i - 1]跳还是从dp[i - 2]跳呢?
//一定是选最小的,所以dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
dep[i] = Math.min((dep[i-1] + cost[i-1]),(dep[i-2] + cost[i-2]));
}
return dep[len];
}
}