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

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

本文通过泰波那契数列、爬楼梯变种及解码方法等四个经典例题,系统讲解一维动态规划的核心思想与实战技巧。重点剖析状态定义、转移方程推导及边界处理,提供 C++ 源码实现与空间优化方案,帮助读者建立动规思维框架并提升解题能力。

热情发布于 2026/3/27更新于 2026/6/1121 浏览
C/C++ 算法入门:一维动态规划基础实战

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

动态规划(Dynamic Programming)是算法面试中的高频考点,也是很多初学者感到棘手的部分。其实掌握核心思路后,它并没有想象中那么难。本文将通过四道经典的一维动态规划题目,带你从状态定义到代码实现,逐步建立解题框架。

核心方法论

动态规划的本质可以概括为:状态定义 + 状态转移方程 + 初始条件 + 状态存储。在实战中,我们通常遵循以下五个步骤来拆解问题:

  1. 状态表示:明确 dp[i] 的含义。通常是以位置 i 结尾或开头的某种最优解或方案数。
  2. 状态转移方程:推导 dp[i] 与之前状态的关系。这是最关键的一步,往往需要结合题目约束进行逆向思考。
  3. 初始化:确定边界值,确保递推过程不越界。
  4. 填表顺序:根据依赖关系决定遍历方向(如从左向右、从右向左)。
  5. 返回值:根据题意从 dp 表中提取最终结果。

提示:在处理数字字符判断时,建议转换为整型后再比较,避免字符编码带来的逻辑漏洞。适当开辟虚拟节点空间往往能简化边界处理。


实战演练

1. 第 N 个泰波那契数

题目描述:计算第 n 个泰波那契数,其中 T0 = 0, T1 = 1, T2 = 1, Tn+3 = Tn + Tn+1 + Tn+2。

思路分析: 这是一个典型的线性递推问题。状态 dp[i] 直接定义为第 i 个泰波那契数。转移方程即为 dp[i] = dp[i-1] + dp[i-2] + dp[i-3]。由于计算当前项只依赖前三项,我们可以使用滚动数组将空间复杂度优化至 O(1)。

代码实现:

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 ( i = ; i <= n; ++i) {
            ret = a + b + c;
            a = b;
            b = c;
            c = ret;
        }
         ret;
    }
};
int
3
return

2. 三步问题

题目描述:小孩每次可以走 1、2 或 3 步,求到达第 n 阶台阶的方法总数。结果需对 10^9+7 取模。

思路分析: 状态 dp[i] 表示到达第 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。由于涉及加法可能溢出,中间计算需强制转换类型并取模。

代码实现:

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];
    }
};

3. 使用最小花费爬楼梯

题目描述:给定一个整数数组 cost,cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦支付费用,你可以选择向上爬一个或者两个台阶。找出达到楼层顶部的最低花费。

思路分析: 这里有两种常见的 DP 定义方式:

  1. 自底向上:dp[i] 表示到达第 i 阶的最小花费。dp[i] = min(dp[i-1], dp[i-2]) + cost[i]。注意楼顶在数组末尾之后,所以最终结果是 min(dp[n-1], dp[n-2])。
  2. 自顶向下: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 或第 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 的消息通过以下方式进行了编码:'A' -> 1, 'B' -> 2, ..., 'Z' -> 26。给定一个只含数字的非空字符串,计算有多少种解码方法。

思路分析: 这是一个带有条件判断的计数问题。dp[i] 表示以第 i 个字符结尾的解码方法数。

  • 如果当前字符 s[i] 非 '0',则可以单独解码,继承 dp[i-1] 的方案数。
  • 如果前两个字符组成的数字在 10~26 之间,则可以组合解码,累加 dp[i-2] 的方案数。
  • 若无法解码(如出现 "06"),则方案数为 0。

技巧:为了统一处理边界,可以在 dp 数组前多开一位作为虚拟节点,令 dp[0]=1,这样 dp[2] 的计算可以直接引用 dp[0],无需特殊判断 i=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) {
            // 单个字符解码
            if (s[i - 1] != '0') {
                dp[i] += dp[i - 1];
            }
            // 两个字符组合解码
            int twoDigit = stoi(s.substr(i - 2, 2));
            if (twoDigit >= 10 && twoDigit <= 26) {
                dp[i] += dp[i - 2];
            }
        }
        return dp[n];
    }
};

总结

通过上述四个案例,我们可以看到一维动态规划的通用模式:先定义状态含义,再寻找状态间的递推关系,最后处理好边界和初始化。在实际刷题过程中,不要死记硬背模板,而应多思考'为什么这么定义'以及'如何从子问题推导父问题'。希望这些内容能帮助你建立起扎实的动规思维框架。

目录

  1. C/C++ 算法入门:一维动态规划基础实战
  2. 核心方法论
  3. 实战演练
  4. 1. 第 N 个泰波那契数
  5. 2. 三步问题
  6. 3. 使用最小花费爬楼梯
  7. 4. 解码方法
  8. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • MySQL 事务与隔离级别深度解析:ACID、MVCC 与间隙锁实战
  • 利用 MaaS 平台 API 构建本地智能 AI 助手
  • 基于 ColQwen2 与 Qwen2.5 的 PDF 多模态 RAG 方案(无需 OCR)
  • Google 推出 Flow AI 电影制作新平台
  • Python 控制周立功 CAN 卡读取总线消息并保存为 BLF 文件
  • 深入理解 Web Worker:Web 前端多线程实战
  • 从 BERT 到 DeepSeek:大模型架构演进、预训练与 RLHF 解析
  • AI 图生图与视频生成完整工作流及提示词参数表
  • YOLOv8 模型部署至高通 RB5 边缘推理平台实战
  • Linux 进程间通信进阶:消息队列与信号量详解
  • 企业级 AI 四层架构:RAG、AI Agents、MCP 与 A2A 协同体系
  • Nginx 部署前端 Vue 项目实战指南
  • 无人机辅助射频探测无线地下土壤健康监测智能钉平台
  • 大模型高效推理与部署技术实战
  • 毕业就业信息管理系统:SpringBoot 后端+Vue 前端+MySQL 实现
  • OpenClaw 与 Claude Code、Cursor、Copilot 的差异解析
  • GitHub Agent HQ 实战:Copilot Pro 接入与代码库全生命周期管理
  • LeetCode 滑动窗口算法初阶详解
  • Web APIs:元素滚动 scroll 系列属性详解(位置与尺寸)
  • AI Agent 持久记忆实战:Claude Code 接入 MemMachine 全流程

相关免费在线工具

  • 加密/解密文本

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