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

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

一维动态规划核心在于状态定义与转移方程。通过泰波那契数、爬楼梯变体及解码方法四个经典例题,演示如何推导状态、处理边界条件及进行空间优化。重点解析虚拟节点技巧与常见陷阱,提供完整的 C++ 实现方案,助力快速掌握动规解题套路。

GopherDev发布于 2026/3/16更新于 2026/8/1944 浏览
C/C++ 算法入门:一维动态规划基础实战

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

动态规划核心概念

动态规划(Dynamic Programming)本质是状态定义 + 状态转移方程 + 初始条件 + 状态存储。简单来说,就是利用已计算出的值来推导当前位置的值。

解题五步法

  1. 状态表示:明确 dp[i] 的含义。通常以 i 位置结尾或开头。
  2. 状态转移方程:推导 dp[i] = ?。这是最关键的一步,需结合题目逻辑。
  3. 初始化:确保填表时不越界,根据题目确定初始值。
  4. 填表顺序:保证计算当前状态时,所需的前置状态已计算完成(通常从左向右或从上到下)。
  5. 返回值:根据题意从 dp 表中提取结果。

提示:处理边界问题时,适当开辟空间或使用虚拟节点往往能简化逻辑。


实战演练

1. 第 N 个泰波那契数

题目描述

求第 n 个泰波那契数,其中 T(0)=0, T(1)=1, T(2)=1, T(n)=T(n-1)+T(n-2)+T(n-3)。

思路分析
  • 状态表示:dp[i] 表示第 i 个泰波那契数。
  • 转移方程:dp[i] = dp[i-1] + dp[i-2] + dp[i-3]。
  • 初始化:dp[0]=0, dp[1]=1, dp[2]=1。
  • 优化:由于只依赖前三个数,可使用滚动数组将空间复杂度降为 O(1)。
代码实现
class Solution {
public:
    int tribonacci(int n) {
        // 普通写法
        if (n == 0) return 0;
        if (n <= 2) return 1;
        
        vector<int> dp(n + 1);
        dp[] = ; dp[] = ; dp[] = ;
        
         ( i = ; i <= n; i++) {
            dp[i] = dp[i - ] + dp[i - ] + dp[i - ];
        }
         dp[n];
    }

    
    {
         (n == )  ;
         (n <= )  ;
        
         a = , b = , c = , ret = ;
         ( i = ; i <= n; i++) {
            ret = a + b + c;
            a = b;
            b = c;
            c = ret;
        }
         ret;
    }
};
0
0
1
1
2
1
for
int
3
1
2
3
return
// 空间优化写法
int tribonacciOptimized(int n)
if
0
return
0
if
2
return
1
int
0
1
1
0
for
int
3
return

2. 三步问题

题目描述

小孩每次可以走 1、2 或 3 步,求到达 n 阶台阶的方法数。

思路分析
  • 状态表示:dp[i] 表示到达第 i 阶的方法数。
  • 转移方程:可以从 i-1、i-2、i-3 走过来,故 dp[i] = dp[i-1] + dp[i-2] + dp[i-3]。
  • 初始化:dp[0]=1 (不动), dp[1]=1, dp[2]=2。
  • 注意:结果可能很大,需对 10^9+7 取模。
代码实现
class Solution {
public:
    int waysToStep(int n) {
        if (n <= 2) return n == 1 ? 1 : 2;
        if (n == 3) return 4;
        
        vector<long long> dp(n + 1);
        dp[0] = 1; dp[1] = 1; dp[2] = 2;
        
        for (int i = 3; i <= n; i++) {
            dp[i] = (dp[i - 1] + dp[i - 2] + dp[i - 3]) % 1000000007;
        }
        return dp[n];
    }
};

3. 使用最小花费爬楼梯

题目描述

给定数组 cost,cost[i] 是从该台阶向上爬的费用。一旦支付费用,可爬 1 或 2 步。求到达楼顶的最小花费。

思路分析
  • 方法一(自底向上):
    • dp[i] 表示到达第 i 层的最小花费。
    • dp[i] = min(dp[i-1], dp[i-2]) + cost[i]。
    • 注意楼顶在数组末尾之后,需额外处理。
  • 方法二(自顶向下):
    • dp[i] 表示从第 i 层出发到达楼顶的最小花费。
    • dp[i] = cost[i] + min(dp[i+1], dp[i+2])。
    • 填表顺序从右向左。
代码实现
class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int n = cost.size();
        vector<int> dp(n + 1);
        
        // 初始化前两阶花费为 0(可从 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' 对应 '1'-'26')。求有多少种解码方式。

思路分析
  • 状态表示:dp[i] 表示以 i 结尾的解码方法总数。
  • 转移方程:
    1. 单个字符解码:若 s[i] 在 1-9 之间,dp[i] += dp[i-1]。
    2. 两个字符解码:若 s[i-1]s[i] 在 10-26 之间,dp[i] += dp[i-2]。
  • 边界处理:使用虚拟节点 dp[0]=1 简化初始化逻辑,避免单独处理第一个字符。
代码实现
class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        vector<int> dp(n + 1, 0);
        
        // 虚拟节点初始化
        dp[0] = 1;
        dp[1] = (s[0] != '0') ? 1 : 0;
        
        for (int i = 2; i <= n; i++) {
            // 单个字符判断
            if (s[i - 1] >= '1' && s[i - 1] <= '9') {
                dp[i] += dp[i - 1];
            }
            // 两个字符判断
            int twoDigit = (s[i - 2] - '0') * 10 + (s[i - 1] - '0');
            if (twoDigit >= 10 && twoDigit <= 26) {
                dp[i] += dp[i - 2];
            }
        }
        return dp[n];
    }
};

总结

掌握一维动态规划的关键在于准确的状态定义和转移方程推导。通过上述四个例题,我们练习了:

  1. 基础递推(泰波那契)。
  2. 组合计数与取模(三步问题)。
  3. 路径优化(最小花费)。
  4. 字符串解析与边界技巧(解码方法)。

在实际刷题中,建议先尝试手动推导小数据量的 DP 表,再编写代码验证。遇到复杂边界时,多开一位数组或使用虚拟节点往往是更优解。

目录

  1. C/C++ 算法入门:一维动态规划基础实战
  2. 动态规划核心概念
  3. 解题五步法
  4. 实战演练
  5. 1. 第 N 个泰波那契数
  6. 题目描述
  7. 思路分析
  8. 代码实现
  9. 2. 三步问题
  10. 题目描述
  11. 思路分析
  12. 代码实现
  13. 3. 使用最小花费爬楼梯
  14. 题目描述
  15. 思路分析
  16. 代码实现
  17. 4. 解码方法
  18. 题目描述
  19. 思路分析
  20. 代码实现
  21. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Python 开发 MongoDB 数据库 MCP Server 实战指南
  • OpenClaw 20 个精选 Skills 使用指南与最佳实践
  • 基于 Python + OpenCV 的人脸识别项目实战:SFaceEmbedding + GUI 训练与评估
  • 平衡二叉树判定:从 O(n²) 暴力递归到 O(n) 自底向上优化
  • Java 注解与反射实战:实现自定义日志与参数校验注解
  • 双指针算法:四数之和解题思路与实现
  • Cursor 配置网络代理的方法与验证
  • 纯文本大模型训练:从 BERT 到 LLaMA 系列高效实践
  • Java 并发常见问题总结
  • 前端崩溃监控:为网页安装生命体征监测系统
  • 搜狗输入法 AI 汪仔进程占用 CPU 过高解决方案
  • Flutter for OpenHarmony 实战:数独算法与求解器深度解析
  • Adobe Downloader macOS 版工具介绍与使用
  • 2024 年 AI+ 教育行业发展及研究报告摘要
  • 25 年编程经验:掌握 30 门语言的心得与历程
  • 群智能算法:灰狼优化算法(GWO)原理与实现
  • 前端 Base64 格式文件上传详解:原理、实现与最佳实践
  • 递归算法专题:汉诺塔、链表操作与快速幂
  • F5 刷新后,浏览器前端究竟发生了什么?
  • C++ 输入输出详解(上):基础流与格式控制

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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