1. 题目链接:746. 使用最小花费爬楼梯
2. 题目描述:
给你一个整数数组
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 。
提示:
2 <= cost.length <= 1000
0 <= cost[i] <= 999
3. 解法1(动态规划)
3.1 算法思路:
- 以
i
位置为结尾
dp[i]
表示到达i
位置时的最小花费(注意:到达i
位置的时候,i
位置的钱不需要算上)
- 状态转移方程:
根据最近的一步,分情况讨论:
先到达i-1
的位置,然后支付cost[i-1]
,接下来走一步到i
位置:dp[i-1]+cost[i-1]
先到达i-2
的位置,然后支付cost[i-2]
,接下来走两步到i
位置:dp[i-2]+cost[i-2]
- 初始化:
从我们的递推公式可以看出,我们需要先初始化i=0
,以及i=1
的位置的值。容易得到dp[0]=dp[1]=0
,因为不需要任何花费,就可以直接站到0
层和第1
层上
-
填表顺序:
根据状态转移方程可得,遍历的顺序是从左往右
-
返回值
根据状态表示以及题目要求,需要返回
dp[n]
位置的值
3.2 C++算法代码:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n=cost.size();
//创建一个pd表
vector<int>dp(n+1,0);
//初始化
dp[0]=dp[1]=0;
//填表
for(int i=2;i<n+1;i++)
{
dp[i]=min(cost[i-1]+dp[i-1],cost[i-2]+dp[i-2]);
}
//返回结果
return dp[n];
}
};
4. 解法2(动态规划)
4.1 算法思路:
- 状态表示:
以i
位置为起点
dp[i]
表示:从i
位置出发,到达楼顶,此时的最小花费
- 状态转移方程:
根据最近的一步,分情况讨论:
支付cost[i]
,往后走一步,接下来从i+1
的位置出发到终点:dp[i+1]+cost[i]
支付cost[i]
,往后走两步,接下来从i+2
的位置出发到终点:dp[i+2]+cost[i]
我们要的是最小花费,因此dp[i]=min(dp[i+1],dp[i+2])+cost[i]
- 初始化
为了保证填表的时候不越界,我们需要初始化最后两个位置,结合状态表示易得:dp[n-1]=cost[n-1]
,dp[n-2]=cost[n-2]
- 填表顺序
根据状态转移方程可得,遍历的顺序是从左往右
- 返回值
- 根据状态表示以及题目要求,需要返回
dp[n]
位置的值
4.2 C++算法代码:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n=cost.size();
//创建dp表
vector<int>dp(n);
//初始化
dp[n-1]=cost[n-1],dp[n-2]=cost[n-2];
//填表顺序
for(int i=n-3;i>=0;i--)
{
dp[i]=min(dp[i+1],dp[i+2])+cost[i];
}
//返回值
return min(dp[0],dp[1]);
}
};