动态规划五个步骤:
- 确定动态数组和下标的含义;
- 确定递推公式;
- 初始化数组;
- 确定遍历方式;
- 举例佐证。
状态:Debug后AC。
可以用递归写,也可以用动态规划来写,使用动态数组之后发现可以用两个值进行替代。这里直接用的最后一种方法,需要注意的是遍历方式的确定,代码如下:
class Solution {
public:
int fib(int n) {
int first = 0, second = 1;
if(n == 0) return first;
int res = 1;
for(int i = 1; i < n; ++i){
res = first + second;
first = second;
second = res;
}
return res;
}
};
状态:Debug查看转移方程后AC。
注意转移方程和初始化的过程,这里不贴最终代码,方便理解五个步骤:
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n+1, 0);
dp[0] = 1, dp[1] = 1;
for(int i = 2; i <= n; ++i){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
};
状态:索引下标和状态转移方程有都问题。
这道题有一个理解上绕的是是要走到楼顶,如果把索引i的含义当作是每个阶梯到楼顶的最小花费,思路会变得很绕,因为可以是前一个阶梯直接到,也可以是前两个阶梯加上这个阶梯的花费,很混乱。所以下标i的含义是到达该阶梯的最小花费,把最高的楼顶当作一个cost为0的阶梯。这样初始化的时候就需要len+1个元素。代码如下:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int len = cost.size();
vector<int> dp(len+1);
dp[0] = 0, dp[1] = 0;
for(int i = 2; i <= len; ++i){
dp[i] = min(dp[i-2]+cost[i-2], dp[i-1]+cost[i-1]);
}
return dp[len];
}
};