跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C/C++ 算法入门:一维动态规划基础实战

动态规划核心在于状态定义与转移方程。本文通过泰波那契数、三步问题、最小花费爬楼梯及解码方法四个经典案例,详解一维 DP 的五步解题法。涵盖状态表示、初始化、填表顺序及空间优化技巧,帮助读者掌握从基础到进阶的 DP 实战思路。

灵魂伴侣发布于 2026/3/24更新于 2026/10/1291 浏览
C/C++ 算法入门:一维动态规划基础实战

动态规划基础

动态规划本质上是某种状态的公式加上一个提前计算好值的容器。通过求出当前位置的值并放入容器中供后续使用,从而解决复杂问题。初始值通常是可见的,由此启动整个计算过程。

严格来说:动态规划 = 状态定义 + 状态转移方程 + 初始条件 + 状态存储

动规五步法

  1. 状态表示:即 dp 表中 dp[i] 的含义,通常结合题目要求分析子问题。
  2. 状态转移方程:推导 dp[i] 的具体计算公式,这是最难的一步。
  3. 初始化:保证填表时不越界,根据题目设定初始值。
  4. 填表顺序:确保计算当前状态时所需的前置状态已计算完成,通常从左向右或从上到下。
  5. 返回值:根据题意从 dp 表中提取最终结果。

提示:状态表示通常为'以 i 位置结尾/开头',dp[i] 通常通过最后一个状态进行分析;初始化通常通过第一个状态进行分析。处理数字字符判断时,建议转换为数字而非直接比较字符,避免边界错误。

实战演练

1. 第 N 个泰波那契数

这道题是典型的线性递推。我们需要求第 n 个泰波那契数,其规律类似于斐波那契数列,但依赖前三个数。

核心逻辑:

  • 状态表示:dp[i] 表示第 i 个泰波那契数。
  • 转移方程:dp[i] = dp[i-1] + dp[i-2] + dp[i-3]。
  • 空间优化:由于只依赖前三个数,可以使用滚动变量代替数组。
class Solution {
public:
    int tribonacci(int n) {
        // 空间优化写法:使用三个变量维护前三个状态
        if (n == 0) return 0;
        if (n == 1 || n == 2) return 1;
        
        int a = 0, b = 1, c = 1;
        int ret = 0;
        for (int i = 3; i <= n; ++i) {
            ret = a + b + c;
            a = b;
            b = c;
            c = ret;
        }
        return ret;
    }
};

实际运行时,注意 n 较小时直接返回初始值,避免循环无效执行。

2. 三步问题

小孩每次可以走 1、2 或 3 步,问到达 n 阶台阶有多少种方法。

核心逻辑:

  • 状态表示:dp[i] 表示到达第 i 阶的方法数。
  • 转移方程:dp[i] = dp[i-1] + dp[i-2] + dp[i-3]。
  • 关键点:需要取模运算防止整数溢出。
class Solution {
public:
    int waysToStep(int n) {
        if (n == 1) return 1;
        if (n == 2) return 2;
        if (n == 3) return 4;
        
        vector<int> dp(n + 1);
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 4;
        
        for (int i = 4; i <= n; ++i) {
            dp[i] = ((long long)dp[i - 1] + dp[i - 2] + dp[i - 3]) % 1000000007;
        }
        return dp[n];
    }
};

这里使用了 long long 强制转换来避免加法过程中的中间溢出,最后再取模。

3. 使用最小花费爬楼梯

每个台阶都有对应的花费,可以从下标 0 或 1 开始,每次向上爬 1 或 2 步,求到达楼顶的最小花费。

核心逻辑:

  • 状态表示:dp[i] 表示到达第 i 层的最小花费。
  • 转移方程:dp[i] = min(dp[i-1], dp[i-2]) + cost[i]。
  • 注意:楼顶在数组末尾之后,所以 dp 数组长度需为 size+1。
class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int n = cost.size();
        vector<int> dp(n + 1);
        
        // 初始化:从 0 或 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];
    }
};

另一种思路是从后往前推,从楼顶倒推回地面,逻辑类似,可根据习惯选择。

4. 解码方法

给定一串数字字符串,将其解码为字母(A-Z),求有多少种解码方式。

核心逻辑:

  • 状态表示:dp[i] 表示前 i 个字符的解码方法数。
  • 转移方程:
    1. 单个字符有效(1-9):dp[i] += dp[i-1]
    2. 两个字符组合有效(10-26):dp[i] += dp[i-2]
  • 边界处理:多开一位虚拟节点 dp[0]=1,简化 dp[1] 的计算。
class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        if (n == 0 || s[0] == '0') return 0;
        
        vector<int> dp(n + 1);
        dp[0] = 1; // 虚拟节点
        dp[1] = 1;
        
        for (int i = 2; i <= n; ++i) {
            int oneChar = s[i - 1] - '0';
            int twoChar = (s[i - 2] - '0') * 10 + oneChar;
            
            if (oneChar >= 1 && oneChar <= 9) {
                dp[i] += dp[i - 1];
            }
            if (twoChar >= 10 && twoChar <= 26) {
                dp[i] += dp[i - 2];
            }
        }
        return dp[n];
    }
};

对于需要判断多位数字的情况,不要偷懒直接用字符比较,务必转换为数值后再进行范围判断,这样更稳健。

总结

通过以上四个案例,我们梳理了一维动态规划的通用解题框架。关键在于准确的状态定义和合理的转移方程推导。在实际编码中,注意边界条件的处理和空间复杂度优化,能让代码更高效且易于维护。

目录

  1. 动态规划基础
  2. 动规五步法
  3. 实战演练
  4. 1. 第 N 个泰波那契数
  5. 2. 三步问题
  6. 3. 使用最小花费爬楼梯
  7. 4. 解码方法
  8. 总结

更多推荐文章

查看全部
  • MySQL 权限管理与 C/C++ 开发对接指南
  • 中国电信发布星辰语音大模型 支持 30 种方言混说
  • PowerShell 中 Invoke-WebRequest 正确使用:避免参数匹配错误
  • JavaScript Proxy 代理机制与核心方法详解

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online