动态规划5部曲:
1.确定dp数组以及下标的含义
2.确定状态转移方程
3.dp数组如何初始化
4.确定遍历顺序
5.举例推导dp数组
本题根据5部曲,首先确定dp数组以及下标含义,dp[i]表示第i个数的斐波那契数值是dp[i]
状态转移方程为dp[i] = dp[i-1]+dp[i-2]
初始化为dp[0] = 0,dp[1] = 1;
根据递归公式确定是从前往后遍历
#include<iostream>
#include<vector>
using namespace std;
class Solution
{
public:
int fib(int n)
{
vector<int>dp(n+1);
//状态转移方程f(n) = f(n-1)+f(n-2)
//初始化dp[0] = 0,dp[1] = 1;
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++)
{
dp[i] = dp[i - 1] + dp[i - 2];
}
int result = dp[n];
return result;
}
};
int main()
{
int n;
cin >> n;
Solution s;
cout << s.fib(n) << endl;
}
1.dp[i]表示爬到第i阶台阶的方法
2.状态转移方程:dp[i] = dp[i-1]+dp[i-2]
(假如要爬到9层台阶,可以先爬到8层台阶再爬1阶到9阶,或者爬到7阶再爬2阶到9,所以到9阶的方法等于爬到7阶的方法与爬到8阶的方法之和)
dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶不就是dp[i]了么。
还有就是dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,那么再一步跳两个台阶不就是dp[i]了么。
那么dp[i]就是 dp[i - 1]与dp[i - 2]之和
3.初始化:爬到1阶的方法只有1种,爬到2阶的方法2种,dp[1] = 1,dp[2] = 2;
4.遍历顺序为从前往后
#include<iostream>
#include<vector>
using namespace std;
class Solution
{
public:
int climbStairs(int n)
{
vector<int>dp(n + 1);
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++)
{
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
};
int main()
{
int n;
cin >> n;
Solution s;
cout << s.climbStairs(n) << endl;
return 0;
}
1.dp[i]表示到达第i台阶所需要的最小体力
2.到达第i级台阶可以从第i-1级台阶跳一个,或者从i-2级跳两个,从i-1级跳一个到i级所需要花费的体力等于跳到i-1级所需体力再加上从i-1跳到1所需的体力,即:dp[i-1]+cost[i-1],从i-2阶跳也是如此,题目要求体力花费的最小值,所以状态转移方程为:
dp[i] =min((dp[i-1]+cost[i-1]),dp[i-2]+cost[i-2]);
3.初始化:dp[0] = 0,dp[1] = 0;
4.遍历顺序为从前往后
#include<iostream>
#include<vector>
using namespace std;
int minCostClimbingStairs(vector<int>& cost)
{
int n = cost.size();
vector<int>dp(n + 1);
dp[0] = 0;
dp[1] = 0;
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];
}
int main()
{
int n;
cin >> n;//输入cost数组的大小
vector<int>cost(n);
for (int i = 0; i < n; i++)
{
cin >> cost[i];
}
int res = minCostClimbingStairs(cost);
cout << res << endl;
}