746. 使用最小花费爬楼梯https://leetcode.cn/problems/min-cost-climbing-stairs/description/给你一个整数数组cost,其中cost[i]是从楼梯第i个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬1个或者2个台阶。你可以选择从下标为0或下标为1的台阶开始爬楼梯。请你计算并返回到达楼梯顶部的最低花费。
- 输入:cost = [10,15,20],输出:15,解释:你将从下标为1的台阶开始。支付15,向上爬2个台阶,到达楼梯顶部。总花费为15。
- 输入:cost = [1,100,1,1,1,100,1,1,100,1],输出:6,解释:你将从下标为0的台阶开始。支付1,向上爬2个台阶,到达下标为2的台阶;支付1,向上爬2个台阶,到达下标为4的台阶;支付1,向上爬2个台阶,到达下标为6的台阶;支付1,向上爬1个台阶,到达下标为7的台阶;支付1,向上爬2个台阶,到达下标为9的台阶;支付1,向上爬1个台阶,到达楼梯顶部。总花费为6。
提示:2 <= cost.length <= 1000,0 <= cost[i] <= 999。
我们用动态规划的思想来解决这个问题。由于cost的下标范围是[0, n - 1],故到达楼梯顶部的最低花费等价于到达n位置的最低花费。
确定状态表示:根据经验和题目要求,我们用dp[i]表示到达i位置的最低花费。
推导状态转移方程:到达i位置的最低花费和最近的一步有关。
- 我们可以先到i - 1位置,支付cost[i - 1],再向上爬1个台阶。由于到i - 1位置的最低花费是dp[i - 1],这种情况总共的最低花费是dp[i - 1] + cost[i - 1]。
- 我们也可以先到i - 2位置,支付cost[i - 2],再向上爬2个台阶。由于到i - 2位置的最低花费是dp[i - 2],这种情况总共的最低花费是dp[i - 2] + cost[i - 2]。
要求的是到达i位置的最低花费,即上面2种情况的较小值,也就是说dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])。
初始化:根据状态转移方程,计算dp[0]和dp[1]时会越界,所以需要初始化。由于可以选择从下标为0或1的位置开始向上爬,所以dp[0] = dp[1] = 0。
填表顺序:根据状态转移方程,dp[i]依赖于dp[i - 1]和dp[i - 2],故应从左往右填表。
返回值:到达楼梯顶部的最低花费等价于到达n位置的最低花费,故应返回dp[n]。
细节问题:由于下标范围是[0, n],故dp表的规模是1 x (n + 1)。
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n = cost.size();
// 创建dp表
vector<int> dp(n + 1);
// 填表
for (int i = 2; i <= n; i++) {
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
}
// 返回结果
return dp[n];
}
};