1、题目解析
好,先来看题目,题目是很简单的,相信大家都可以看懂,这道题要注意的是,楼顶位置在哪里。我们可以先看示例1。示例1是直接从下标为1的台阶向上爬了两步到达楼梯顶部。也就是说,楼顶在下标为n的位置。而不是n-1的位置,这一点特别重要。如果没有注意这一点是做不对这道题的,我第一次做的时候就没有注意这个细节。废话不多说,那就直接用动态规划来解决一下这个问题吧。
二、算法原理
动态规划的步骤就是那五步,我们先来分析一个状态表示。
1、状态表示:
这道题目让我们干什么,它让我们求到达楼梯顶部此时的最小花费。好,那我们先按照题目的要求直接定一个状态表示。如果能分析出来状态转移方程,说明状态表示定义是对的。我们做动态规划题目的时候,要大胆定义状态表示,不要怕错。如果错了在分析就好了。
dp[i]表示:爬到第i个台阶的最小花费。
2、状态转移方程:
其实我们在推导状态转移方程的时候是有技巧规律可寻的,我们可以根据之前的状态或者之后的状态看看能不能推导出当前的状态。i号台阶看着很麻烦而且不容易理解,我就用i位置来代替了。
题目告诉我们可以每次走一个台阶,或者两个台阶。因此,如果我们要到达i位置,我们只可能从i-1 或者i - 2的位置到达i位置。我们如果从i - 1的位置到达i位置,我们仅需要知道到达i - 1位置的最小花费然后支付i-1位置的花费爬一个台阶,就可以到达i位置。好,那么到达i-1的最小花费在哪里呢?不就在dp[i - 1]里面吗?我们看看我们的状态表示,我们的状态表示是爬到第i个台阶的最小花费。那么dp[i - 1]不就是爬到第i-1个台阶的最小花费吗?因此,dp[i] = dp[i - 1] + cost[i - 1]同理,从i - 2位置到达i位置也是一样的。我们仅需要知道到达i - 2位置的最小花费然后再支付i-2位置的花费爬二个台阶,就可以到达i位置。因此,dp[i] = dp[i - 2] + cost[i - 2]。题目要求出到达楼顶位置的最小花费,因此两者取一个最小值即可。
所以dp[i] = min(dp[i - 1]+ cost[i - 1], dp[i - 2] + cost[i - 2])。
3、初始化:
因为楼顶的位置在n位置,因此我们开数组的时候要多开1个。至于初始化,我们填i的时候要用到i-1和i-2位置的状态,因此我们仅需初始化下标0和1位置即可。那么初始化成什么呢?题目告诉我们可以从0号下标和1号下标开始爬楼梯,因此我们达到0号和1号位置·的时候是不需要支付费用的。因此,0和1的位置初始化成0即可。因为C++vector的数组是默认初始化成0的,因此不需要初始化。
4、填表顺序:
从状态转移方程我们就可以看出,我们填i位置的时候是需要用到前2个位置的状态,因此填表顺序是从左往右的。我们需要用到前2个位置的状态,因此从2号下标开始填表。
5、返回值
题目要求,到达楼顶的最小花费。因此返回dp[n]即可。
希望大家可以根据算法原理自己尝试一下编写代码。
三、编写代码
class Solution
{
public:
int minCostClimbingStairs(vector<int>& cost)
{
//返回dp[b];
int n = cost.size();
//1.创建一个dp表
vector<int> dp(n + 1);
//2.根据状态转移方程填表
for(int i = 2; i <= n; i++)
{
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
}
//3.返回结果
return dp[n];
}
};