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

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

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


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

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

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

2. 代码详解

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

复制代码

cpp

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

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

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

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

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++ 创建二维数组的标准方式。

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

谢谢

相关推荐
jsjzsl214 小时前
独立自由度框架下核聚变的本体论本质与商业化技术新路径
人工智能·python·算法
无忧.芙桃14 小时前
C++内存管理
c语言·开发语言·c++·青少年编程
金金计较.14 小时前
Go语言-2
开发语言·算法·golang
郝学胜_神的一滴14 小时前
C++11 工程级应用 11:编译期黑魔法,告别重复烂代码
c++·visual studio
计算机编程-吉哥14 小时前
基于机器学习的城市交通拥堵分析与预测平台【计算机毕业设计选题·机器学习·随机森林算法】
hadoop·算法·随机森林·机器学习·课程设计·计算机毕业设计选题·大数据毕业设计选题推荐
zyeyeye15 小时前
C++入门:从HelloWorld到命名空间揭秘
c语言·开发语言·c++·算法
牧羊人.33315 小时前
动手学深度学习 04 | Dataset 和 DataLoader、数据增强
人工智能·pytorch·深度学习·算法
励志不掉头发的内向程序员15 小时前
【LibreCAD 2D架构】从 addHistory 到 RS_UndoCycle:LibreCAD 里的两套 History 与撤销机制
开发语言·c++·qt·学习·系统架构
elseif12315 小时前
【双指针/二分】P1102 A-B 数对
c++·算法·二分·双指针
电梯界知识分子15 小时前
江西抚州临川九尊府五层别墅:受限楼梯间里,全黑铝合金观光井道配曳引龙门架的落地记录
大数据·前端·网络·算法·家用电梯