【C++】动态规划题目总结(随做随更)

文章目录

一. 斐波那契数列模型

解题步骤:

  1. 确定状态表示(最重要):明确dp表里的值所表示的含义
  2. 推导状态转移方程(最难):dp[i] 等于什么?
  3. 初始化:保证填表的时候不越界
  4. 填dp表:通过前面已经计算过的状态来推导当前状态的值
  5. 返回结果

1. 第 N 个泰波那契数

题目解析

我们对题目给的公式进行转化:

观察公式可以看到,如果要求第 i 个泰波那切数的话,我们只需知道前 i-1、i-2、i-3 的值即可。

算法原理

  • 状态表示:dp[i] 代表第 i 个泰波那切数
  • 状态转移方程:dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
  • 初始化:dp[0] = 1、dp[1] = 1、dp[2] = 1
  • 填表:根据状态转移方程和初始化的值,使用滑动窗口的方式一直计算最终得到第 i 个泰波那切数。
  • 返回值:第 n 个泰波那切数

编写代码

python 复制代码
class Solution {
public:
    int tribonacci(int n) 
    {
        // 1、建表
        // 2、初始化
        // 3、填表
        // 4、返回值

        vector<int> dp(n+1);

        dp[0] = 0, dp[1] = dp[2] = 1;

        for(int i = 3; i <= n; ++i)
        {
            dp[i] = dp[i-1] + dp[i-2] + dp[i-3];
        }

        return dp[n];
    }
};

/*
- 时间复杂度:O(n)
- 空间复杂度:O(n)
*/

2. 三步问题


题目解析 :小孩最多一次跳三步,假设要跳到第n级台阶,那最后跳到第n级台阶时的那一步一定是下面三种情况之一:

所以想求跳到第n级台阶有几种方法的话,我们只需知道跳到第 n-1、n-2 和 n-3 台阶时各自有几种方法,然后把它们相加起来即可。

PS:计算时需要注意取模

算法原理

  • 状态表示:dp[i] 表示 到达i位置时,一共有多少种方法。
  • 状态转移方程:dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
  • 初始化:dp[1] = 1 dp[2] = 2 dp[3] = 4
  • 填表顺序:从左往右
  • 返回值 :dp[n]

代码实现

cpp 复制代码
class Solution
{
public:
	int waysToStep(int n)
	{
		// 1、处理特殊情况
		if (n == 1) return 1;
		if (n == 2) return 2;
		if (n == 3) return 4;
		// 2、创建dp表
		vector<int> dp(n + 1);
		// 3、初始化
		dp[1] = 1;
		dp[2] = 2;
		dp[3] = 4;
		// 4、填表
		for (size_t i = 4; i <= n; ++i)
			dp[i] = ((dp[i - 1] + dp[i - 2]) % 1000000007 + dp[i - 3]) % 1000000007;
		// 5、返回值
		return dp[n];
	}
};

/*
- 时间复杂度:O(n)
- 空间复杂度:O(n)
*/

3. 使用最小花费爬楼梯


题目解析

解法一:从左往右填表

  • 状态表示:dp[i] 表示到达i位置时的最小花费
  • 状态转移方程
  • 初始化(保证填表的时候不越界):dp[0]=dp[1]=0
  • 填表顺序:从左往右
  • 返回值:因为是从0号台阶开始,所以最后一个台阶的下标为 n-1。最后返回 dp[n]

代码实现

cpp 复制代码
class Solution
{
public:
	int minCostClimbingStairs(vector<int>& cost)
	{
		// 创建dp表
		size_t n = cost.size();
		vector<int> dp(n + 1);
		// 填表
		for (size_t i = 2; i <= n; ++i)
			dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
		// 返回值
		return dp[n];
	}
};

/*
- 时间复杂度:O(n)
- 空间复杂度:O(n)
*/

解法二:从右往左填表

  • 状态表示:dp[i] 表示从i位置出发,到达楼顶,此时的最小花费

  • 状态转移方程

  • 初始化:dp[n-1] = cost[n-1]、dp[n-2] = cost[n-2]

  • 填表顺序:从右往左

  • 返回值:min(dp[0], dp[1])

代码实现

cpp 复制代码
class Solution
{
public:
	int minCostClimbingStairs(vector<int>& cost)
	{
		int n = cost.size();
		vector<int> dp(n);
		dp[n - 1] = cost[n - 1];
		dp[n - 2] = cost[n - 2];
		for (int i = n - 3; i >= 0; --i)
			dp[i] = cost[i] + min(dp[i + 1], dp[i + 2]);
		return min(dp[0], dp[1]);
	}
};

/*
- 时间复杂度:O(n)
- 空间复杂度:O(n)
*/
相关推荐
Vect__3 小时前
基于线程池从零实现TCP计算器网络服务
c++·网络协议·tcp/ip
naruto_lnq8 小时前
分布式系统安全通信
开发语言·c++·算法
YYuCChi10 小时前
代码随想录算法训练营第三十七天 | 52.携带研究材料(卡码网)、518.零钱兑换||、377.组合总和IV、57.爬楼梯(卡码网)
算法·动态规划
CSDN_RTKLIB10 小时前
【四个场景测试】源文件编码UTF-8 BOM
c++
肉包_51111 小时前
两个数据库互锁,用全局变量互锁会偶发软件卡死
开发语言·数据库·c++
Trouvaille ~12 小时前
【Linux】UDP Socket编程实战(一):Echo Server从零到一
linux·运维·服务器·网络·c++·websocket·udp
HellowAmy12 小时前
我的C++规范 - 线程池
开发语言·c++·代码规范
czy878747512 小时前
const 在 C/C++ 中的全面用法(C/C++ 差异+核心场景+实战示例)
c语言·开发语言·c++
十五年专注C++开发12 小时前
MinHook:Windows 平台下轻量级、高性能的钩子库
c++·windows·钩子技术·minhook
罗湖老棍子12 小时前
括号配对(信息学奥赛一本通- P1572)
算法·动态规划·区间dp·字符串匹配·区间动态规划