深圳幻海软件技术有限公司 欢迎您!

【AcWing刷题】蓝桥杯专题突破-动态规划-dp入门(17)

2023-04-12

目录写在前面:题目:821.跳台阶-AcWing题库题目描述:输入格式:输出格式:数据范围:输入样例:输出样例:解题思路:方法一:暴力搜索代码方法二:记忆化搜索代码方法三:动态规划 代码AC!!!!!!!!!!写在最后:写在前面:怎么样才能学好一个算法?我个人认为,系统性的刷题尤为重要,所

目录

写在前面:

题目:821. 跳台阶 - AcWing题库

题目描述:

输入格式:

输出格式:

数据范围:

输入样例:

输出样例:

解题思路:

方法一:暴力搜索

代码

方法二:记忆化搜索

代码

方法三:动态规划

 代码

AC !!!!!!!!!!

写在最后:


写在前面:

怎么样才能学好一个算法?

我个人认为,系统性的刷题尤为重要,

所以,为了学好动态规划,应对 “DP杯”。

事不宜迟,我们即刻开始刷题!

题目:821. 跳台阶 - AcWing题库

题目描述:

一个楼梯共有 n 级台阶,每次可以走一级或者两级,

问从第 0 级台阶走到第 n 级台阶一共有多少种方案。

输入格式:

共一行,包含一个整数 n。

输出格式:

共一行,包含一个整数,表示方案数。

数据范围:

1 ≤ n ≤ 15

输入样例:

5

输出样例:

8

解题思路:

这道题是一道经典的dp入门题目,

我打算使用三种方法去做,层层推进,一起入门递归:

方法一:暴力搜索

这道题在之前dfs的刷题中也有出现,

我们可以用dfs搜索所有的方案:

跳三级台阶就是跳两级台阶的方法+跳一级台阶的方法;

跳四级台阶就是跳三级台阶的方法+跳二级台阶的方法;

以此类推: 

最后得出答案:

代码如下:

代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. using namespace std;
  6. int n = 0;
  7. int dfs(int u)
  8. {
  9. if(u == 1) return 1;
  10. else if(u == 2) return 2;
  11. return dfs(u - 1) + dfs(u - 2);
  12. }
  13. int main()
  14. {
  15. scanf("%d", &n);
  16. int res = dfs(n);
  17. printf("%d", res);
  18. return 0;
  19. }

方法二:记忆化搜索

实际上第一种方法的时间复杂度太高,

有2的n次方那么大:

如果n >= 42,就会超时:

 

为了减少时间的消耗,我们可以用记忆化搜索:

将已经求过的值记录到一个数组中,

这样搜索过的值就不用重复搜索:

 下面是代码实现:

代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. using namespace std;
  6. int n = 0;
  7. int sum = 0;
  8. const int N = 30;
  9. int mem[N];//用一个数组记录
  10. int dfs(int u)
  11. {
  12. if(mem[u]) return mem[u];//如果记录过,就不用往下搜索了
  13. if(u == 1) return 1;
  14. else if(u == 2) return 2;
  15. else sum = dfs(u - 1) + dfs(u - 2);
  16. mem[u] = sum;//将该位置的值记录进数组
  17. return mem[u];
  18. }
  19. int main()
  20. {
  21. scanf("%d", &n);
  22. int res = dfs(n);
  23. printf("%d", res);
  24. return 0;
  25. }

我们发现这样之后,就算n = 100,也只需要1ms:

方法三:动态规划

我们发现,其实这道题动态规划的

状态表达式就是由暴力搜索推出来的,

递归搜索是从上往下搜索,

再从下往上回溯,

其实得出的结果的过程就是在回溯的时候:

那我们可以不用搜索这个过程,直接从下往上递推,

这就是动态规划:

下面是代码实现:

 代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. using namespace std;
  6. int n = 0;
  7. const int N = 30;
  8. int fib[N];
  9. int main()
  10. {
  11. scanf("%d", &n);
  12. fib[1] = 1;
  13. fib[2] = 2;
  14. if(n == 1 || n == 2)
  15. {
  16. printf("%d", fib[n]);
  17. return 0;
  18. }
  19. for(int i = 3; i <= n; i++)
  20. {
  21. //这个就是动态规划的状态表达式
  22. fib[i] = fib[i - 1] + fib[i - 2];
  23. }
  24. printf("%d", fib[n]);
  25. return 0;
  26. }

AC !!!!!!!!!!

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果喜欢本文的话,欢迎点赞和评论,写下你的见解。

如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。

之后我还会输出更多高质量内容,欢迎收看。

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览43883 人正在系统学习中