备战蓝桥 2022-1-2

x33g5p2x  于2022-01-04 转载在 其他  
字(1.9k)|赞(0)|评价(0)|浏览(256)

动态规划

网上有很多讲动态规划的文章,鱼龙混杂,所以作者在这里就不再多赘述了,推荐一篇觉得写动态规划写的比较好的文章,动态规划理论基础

斐波那契数

斐波那契数

思路

这是一道大家刚刚接触c语言时都写过的题目,相信大家那时基本都是用递归的方法来写的,但递归的复杂度一般都很高,这道题为O(2^N),显然在算法比赛中这种写法是不适用的。

  1. /* 递归的写法 if(n==0) { return 0; } if(n==1) { return 1; } return fib(n-1)+fib(n-2); */

其实这道题可以用dp来写,因为当前状态dp[i]可以看作是由前两个状态dp[i-1]和dp[i-2]得到的,自然就会想dp的方向想。

  1. //第一步确定dp数组的含义:dp[i] 表示第i个斐波那契数
  2. int dp[40]={0};
  3. //第二步确定状态转移方程:dp[i]=dp[i-1]+dp[i-2];
  4. //第三步:初始化 dp[0]=0,dp[1]=1;
  5. //第四步:确定遍历顺序,dp[i]是依赖 dp[i - 1] 和 dp[i - 2],那么遍历的顺序一定是从前到后遍历的
  6. dp[1]=0,dp[2]=1;
  7. if(n+1==1)
  8. {
  9. return dp[1];
  10. }
  11. if(n+1==2)
  12. {
  13. return dp[2];
  14. }
  15. for(int i=3;i<=n+1;i++)
  16. {
  17. dp[i]=dp[i-1]+dp[i-2];
  18. }
  19. return dp[n+1];

爬楼梯

爬楼梯
其实这道题就是把上面拿到题换了一个表达形式而已。

  1. class Solution {
  2. public:
  3. int climbStairs(int n)
  4. {
  5. //第一步:确定dp数组的含义:dp[i]表示爬上第i阶的方法
  6. vector<int> dp(n+2,0); //这儿写的时候要注意,不能写成n+1,因为如果n==1的话,那么长度为2,也就只有dp[0],dp[1]这两个元素了,会造成空指针的访问问题
  7. //第二步:确定状态转移方程,dp[i]=dp[i-1]+dp[i-2],因为到达第i层,只有从第i-1或者i-2
  8. //层才能到达
  9. //第三步:初始化:dp[1]=1,dp[2]=2
  10. //第四步:确定遍历顺序,很显然,我们要从前面的状态推导到后面的状态,因此要顺序遍历
  11. dp[1]=1,dp[2]=2;
  12. if(n==1) return 1;
  13. if(n==2) return 2;
  14. for(int i=3;i<=n;i++)
  15. {
  16. dp[i]=dp[i-1]+dp[i-2];
  17. }
  18. return dp[n];
  19. }
  20. };

使用最小花费爬楼梯

使用最小花费爬楼梯

这一题和前面两个依然很类似,只不过中间掺杂了一个费用这个量。
注意:这道题虽然简单,但是在理解题意时一定要注意,理解dp数组时一定要深刻,结合题目做到合理的理解。

  1. class Solution {
  2. public:
  3. int minCostClimbingStairs(vector<int>& cost)
  4. {
  5. //第一步:确定dp数组的含义:dp[i]表示爬到第i个台阶的最低花费,并且你可以选择从第i层往上爬了
  6. //也就是说你花费了cost[i]。
  7. int size=cost.size(); //下标为size的地方是楼顶
  8. vector<int> dp(size,0);
  9. //第二步:初始化:dp[1]=cost[0],dp[2]=min(cost[0],cost[1]); (这是一开始错误的理解方式)
  10. //第三步:确定状态转移方程:dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]); (这是一开始错误的理解方式)
  11. //第四步:确定遍历顺序:因为状态转移方程是从前一个状态推导后面一个状态,所以是顺序遍历
  12. //dp[1]=cost[0],dp[2]=min(cost[0],cost[1]); //注意题目中说的那句话,你可以从第0层或第1层
  13. // 开始爬楼梯,也就是说你的起点可以由两种不同的
  14. //选择方式,正好对应了dp状态转移方程需要的两个
  15. //初始化,再结合dp数组的定义,因此
  16. //dp[0]=cost[0],dp[1]=cost[1];
  17. dp[0]=cost[0],dp[1]=cost[1];
  18. for(int i=2;i<size;i++)
  19. {
  20. //dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);对dp数组理解的不够深刻
  21. dp[i]=min(dp[i-1],dp[i-2])+cost[i];
  22. }
  23. return min(dp[size-1],dp[size-2]); //从我们dp数组的定义看,到第i层时,需要把自己这一层往上爬的费用也付了,因此只要比较最后一层和最后两层的最小值即可,因为根据我们dp数组的定义可以得到。
  24. }
  25. };

相关文章