当前位置: 首页 > news >正文

《动态规划:从“傻傻穷举”到“过目不忘”的修仙之路》

递归像“查字典”,查一个词,发现要先查另一个词,另一个词又要查第三个词,直到查到最简单的词(Base Case)才停止。

DP 像“考前抱佛脚背书”,把查过的词条直接抄在 A4 纸上(DP数组),考试时直接看纸,不用翻书。


模块一:斐波那契数列(递归 vs 记忆化 vs 递推)

1. 思路讲解(Why C++?)

在 C++ 中,递归深度过深(如n > 10000)会导致栈溢出(Stack Overflow)。而且 C++ 没有 Python 那样的字典(dict)天然支持,我们需要手动开数组。

2. 代码详解

版本 A:纯递归(反面教材,仅用于理解)

cpp

cpp

#include <iostream> using namespace std; int fib(int n) { if (n <= 1) return n; return fib(n - 1) + fib(n - 2); } int main() { cout << fib(5) << endl; // 5 return 0; }
  • 思路:最直观的数学定义。

  • 缺点:时间复杂度 O(2n),存在大量重复计算。

版本 B:记忆化搜索(自顶向下)

cpp

cpp

#include <iostream> #include <vector> using namespace std; int fibHelper(int n, vector<int>& memo) { // 1. 查表:如果算过,直接返回 if (memo[n] != -1) { return memo[n]; } // 2. 计算:没算过,则计算并存入表中 memo[n] = fibHelper(n - 1, memo) + fibHelper(n - 2, memo); return memo[n]; } int fib(int n) { if (n <= 1) return n; // 初始化备忘录,-1表示未计算 vector<int> memo(n + 1, -1); memo[0] = 0; memo[1] = 1; return fibHelper(n, memo); }
  • 思路

    1. 定义一个memo数组(C++ Vector),初始化为-1

    2. 进入函数先判断memo[n]是否不为-1,如果是,直接返回(剪枝)。

    3. 否则计算,并把结果存进memo[n]

  • 注意:这里使用了引用传参vector<int>& memo,避免数组拷贝的巨大开销。

版本 C:动态规划(自底向上,推荐)

cpp

cpp

int fib(int n) { if (n <= 1) return n; vector<int> dp(n + 1); // dp[i] 表示第 i 个斐波那契数 dp[0] = 0; // Base Case dp[1] = 1; // Base Case for (int i = 2; i <= n; i++) { dp[i] = dp[i - 1] + dp[i - 2]; // 状态转移方程 } return dp[n]; }
  • 思路:从最小的子问题开始,一步步构建大问题的解。像织毛衣一样,一行一行织上去。


模块二:爬楼梯(理解 DP 数组定义)

1. 思路讲解

这是 DP 定义的经典题。关键在于定义dp[i]的含义:爬到第 i 阶楼梯的方法总数

由于每次只能爬 1 或 2 阶,所以第 i 阶只能由第 i-1 阶(走 1 步)或第 i-2 阶(走 2 步)到达。

因此:dp[i] = dp[i-1] + dp[i-2]

2. 代码详解

cpp

cpp

#include <vector> using namespace std; class Solution { public: int climbStairs(int n) { if (n <= 2) return n; vector<int> dp(n + 1); // 多开一位,防止 n=1 时越界 dp[1] = 1; // 1阶:1种 dp[2] = 2; // 2阶:2种 (1+1 或 2) for (int i = 3; i <= n; i++) { dp[i] = dp[i - 1] + dp[i - 2]; } return dp[n]; } };
  • C++ 坑点:如果vector<int> dp(n),下标范围是[0, n-1]。如果访问dp[n]会越界。所以通常开n+1方便理解。


模块三:最小路径和(二维 DP 入门)

1. 思路讲解

想象一个棋盘,dp[i][j]代表从左上角(0,0)走到当前格子(i,j)的最小路径和。

要到达(i,j),只能从上方(i-1,j)或左方(i,j-1)过来。

所以:dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])

特例:第一行只能从左来,第一列只能从上来。

2. 代码详解

cpp

cpp

#include <vector> #include <algorithm> using namespace std; class Solution { public: int minPathSum(vector<vector<int>>& grid) { int m = grid.size(); int n = grid[0].size(); vector<vector<int>> dp(m, vector<int>(n, 0)); // 1. 初始化起点 dp[0][0] = grid[0][0]; // 2. 初始化第一列(只能从上往下) for (int i = 1; i < m; i++) { dp[i][0] = dp[i - 1][0] + grid[i][0]; } // 3. 初始化第一行(只能从左往右) for (int j = 1; j < n; j++) { dp[0][j] = dp[0][j - 1] + grid[0][j]; } // 4. 填充剩余格子 for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { // 核心:取上方和左方的最小值,加上当前格子的代价 dp[i][j] = grid[i][j] + min(dp[i - 1][j], dp[i][j - 1]); } } return dp[m - 1][n - 1]; } };
  • 思路拆解

    • vector<vector<int>> dp(m, vector<int>(n, 0));这是 C++ 创建二维数组的标准方式。

    • 初始化边界是新手最容易漏掉的地方,漏了就会逻辑错误。

谢谢
http://www.cnnetsun.cn/news/3283012.html

相关文章:

  • 2026 技术小白也能上手:维护简单、稳定不卡顿的商城小程序平台
  • Cache 性能分析实验:MyCache 模拟器 3 大参数(容量/相联度/块大小)对失效率影响实测
  • 银河麒麟V10 Python 3.7 环境配置:pip 换源与 virtualenv 创建 2 大常见报错解决
  • 2026中小商家线上店铺开通工具排行,哪款最适合新手?
  • PyTorch 2.7.0 离线部署:3步完成CUDA 12.6环境whl文件下载与安装
  • LangChain核心原理:大模型应用的工程化操作系统
  • Unity项目性能优化全攻略:从CPU、GPU到内存管理的实战解析
  • GitHub Copilot 深度原理:三层上下文与注释驱动开发实战
  • 光储充一体化系统 2024:3大核心组件选型与5个典型场站收益分析
  • 终极解决方案:如何用VisualCppRedist AIO一键修复Windows系统依赖问题
  • Treemix 1.13 四倍体分析实战:从 VCF 到 OptM 最优 m 值判定的 5 步流程
  • 为什么FanControl能解决你的电脑风扇噪音和散热问题?
  • Navicat重置脚本:macOS开发者必备的智能试用期管理方案
  • RTP RFC 3550 协议解析:12字节头部详解与Wireshark抓包实战
  • Lito无人机为何是新手入门的最优解
  • 深度实战指南:在Amlogic S905W电视盒上高效部署Armbian系统
  • DDD 实战:从事件风暴到微服务边界,3步完成电商订单域拆分
  • CAD 2020 数据提取功能实战:8步从DLG图层精准导出高程点TXT
  • llama-cpp-python深度解析:ctypes零拷贝与GGUF本地大模型加速原理
  • 2026年企业门户选型全对比:中大型政企如何选型?
  • 技术博客内容生成的安全边界与合规准则
  • ChatGPT API接入全流程拆解(Key管理→Token流控→Error Code 429应急响应→审计日志埋点)
  • RISC-V 五级流水线数据冒险:5种场景Verilog代码实现与仿真波形分析
  • 如何快速实现自动化学习:3个简单步骤的终极指南
  • MA12070音频放大器与PIC18F86J16 MCU的高效音频系统设计
  • 别再盲目打卡一万步!研究发现:每天走够这个数,健康性价比最高!
  • 用豆包编程2.0打造零依赖本地工作计时器
  • 当经典遇上现代:D2DX如何让暗黑破坏神2在4K时代重获新生
  • 专业高效:为Blender添加完整3MF格式支持,打造3D打印工作流终极解决方案
  • Proteus 8.16安装失败原因与深度排错指南