前言
整篇笔记共分为十章,都是博主在准备25年蓝桥杯时所写,听的网课是这个,讲的非常好,很适合零基础速成,如果有听不懂的可以多听几遍
目录如下:
1.Python语法基础及算法入门
2.语法进阶&常用数据结构&算法入门
3.贪心&排序
4.哈希&暴力&前缀
5.二分查找&二分答案
6.搜索&BFS&DFS
7.[数据结构]并查集&堆
8.动态规划
9.图论
10.数论基础&日期问题
目录
[1. DP 的适用条件](#1. DP 的适用条件)
[2. DP 解题四步框架(蓝桥杯通用)](#2. DP 解题四步框架(蓝桥杯通用))
[步骤 1:状态定义](#步骤 1:状态定义)
[步骤 2:确定初始状态](#步骤 2:确定初始状态)
[步骤 3:推导状态转移方程](#步骤 3:推导状态转移方程)
[步骤 4:确定最终答案](#步骤 4:确定最终答案)
[3. DP 的两种实现方式](#3. DP 的两种实现方式)
[4. DP 的空间优化(蓝桥杯高频技巧)](#4. DP 的空间优化(蓝桥杯高频技巧))
[二、蓝桥杯高频一维 DP 题型与模板](#二、蓝桥杯高频一维 DP 题型与模板)
[题型 1:斐波那契数列型(线性递推)](#题型 1:斐波那契数列型(线性递推))
[Python 模板(含空间优化)](#Python 模板(含空间优化))
[题型 2:最大子序和(子序列型)](#题型 2:最大子序和(子序列型))
[Python 模板(含空间优化)](#Python 模板(含空间优化))
[题型 3:打家劫舍(间隔选择型)](#题型 3:打家劫舍(间隔选择型))
[Python 模板(含空间优化)](#Python 模板(含空间优化))
[三、蓝桥杯高频二维 DP 题型与模板](#三、蓝桥杯高频二维 DP 题型与模板)
[题型 1:二维网格最短路径和(网格型 DP)](#题型 1:二维网格最短路径和(网格型 DP))
[Python 模板(含空间优化)](#Python 模板(含空间优化))
[题型 2:01 背包问题(背包型 DP,蓝桥杯重中之重)](#题型 2:01 背包问题(背包型 DP,蓝桥杯重中之重))
[子题型 1:01 背包(每个物品仅能选一次)](#子题型 1:01 背包(每个物品仅能选一次))
[Python 模板(含空间优化,蓝桥杯必考)](#Python 模板(含空间优化,蓝桥杯必考))
[子题型 2:完全背包(每个物品可选无限次)](#子题型 2:完全背包(每个物品可选无限次))
[Python 模板(优化版,蓝桥杯必考)](#Python 模板(优化版,蓝桥杯必考))
[题型 3:最长公共子序列(LCS,双序列型)](#题型 3:最长公共子序列(LCS,双序列型))
[Python 模板](#Python 模板)
[四、蓝桥杯 DP 实战技巧与避坑指南](#四、蓝桥杯 DP 实战技巧与避坑指南)
[1. 状态定义的核心技巧](#1. 状态定义的核心技巧)
[2. 蓝桥杯高频避坑点](#2. 蓝桥杯高频避坑点)
[3. 蓝桥杯 DP 刷题优先级](#3. 蓝桥杯 DP 刷题优先级)
[4. Python 优化 DP 运行速度的技巧](#4. Python 优化 DP 运行速度的技巧)
论文投稿:
第三届边缘计算与并行、分布式计算国际学术会议(ECPDC 2026)
大会时间:2026年8月7-9日
大会地点:新加坡



一、动态规划核心基础
1. DP 的适用条件
必须同时满足以下两个条件,才适合用 DP 解决:
- 重叠子问题:原问题拆解的子问题会被多次重复计算(暴力递归会做大量无用功,DP 用数组 / 字典存储子问题解);
- 最优子结构:原问题的最优解可以由子问题的最优解推导而来(子问题的解独立,无后效性)。
无后效性:某一阶段的子问题解确定后,不受后续阶段的决策影响(即未来的状态不会改变过去的状态),是 DP 的关键前提。
2. DP 解题四步框架(蓝桥杯通用)
这是解决所有 DP 问题的核心思路,无论简单还是复杂题型,都按此步骤拆解,避免思路混乱:
步骤 1:状态定义
定义dp 数组 / 字典 的含义,是 DP 的灵魂,也是最关键的一步。
- 格式:
dp[i]/dp[i][j]表示在某一条件下(i/j 的含义),问题的最优解 / 可行解 / 方案数; - 维度:根据问题的决策维度确定,一维 DP 解决单状态决策问题,二维 DP 解决双状态决策问题(蓝桥杯以一维、二维为主,三维极少)。
- 示例:
dp[i]表示前 i 个元素的最大子序和;dp[i][j]表示从左上角走到第 i 行第 j 列的最短路径和。
步骤 2:确定初始状态
初始化 dp 数组的边界值 ,即子问题的最小解 (无需推导,直接确定的解),是 DP 的起点。
- 示例:
dp[0] = 0(前 0 个元素和为 0);dp[0][j] = dp[0][j-1] + grid[0][j](第一行只能从左边走)。
步骤 3:推导状态转移方程
根据最优子结构 ,找到dp[i]与前面子问题解 的关系,是 DP 的核心。
- 核心:当前状态 = 由前序状态通过决策推导而来;
- 示例:斐波那契数列
dp[i] = dp[i-1] + dp[i-2];01 背包dp[j] = max(dp[j], dp[j-w[i]] + v[i])。
步骤 4:确定最终答案
根据状态定义,确定 dp 数组的最终取值是原问题的解。
- 示例:前 n 个元素的最大子序和答案为
dp[n];从 (0,0) 到 (m-1,n-1) 的最短路径和答案为dp[m-1][n-1]。
3. DP 的两种实现方式
蓝桥杯 Python 中常用两种实现方式,根据问题复杂度选择:
(1)自底向上(迭代法,推荐)
从最小的子问题 开始推导,逐步计算出原问题的解,用循环 实现,效率高,无递归深度问题,是蓝桥杯首选方式。
- 特点:直接操作 dp 数组,符合 Python 的性能要求,适配大数据量;
- 适用:所有 DP 题型,尤其是一维、二维 DP。
(2)自顶向下(记忆化递归)
从原问题 开始,递归拆解为子问题,用字典 / 数组 存储已计算的子问题解(避免重复计算),本质是暴力递归 + 缓存。
- 特点:思路直观,符合人的思考逻辑,适合状态定义较复杂的问题;
- 注意:Python 默认递归深度约 1000,若问题规模超过 1000,需用sys.setrecursionlimit() 扩大深度,否则会栈溢出。
4. DP 的空间优化(蓝桥杯高频技巧)
很多 DP 问题的状态转移仅依赖前 1/2 个状态 ,此时可通过滚动数组 / 变量 替代 dp 数组,将空间复杂度从O(n)/O(nm)优化为O(1)/O(n),适合蓝桥杯中空间限制较严格的题目。
- 示例:斐波那契数列
dp[i] = dp[i-1] + dp[i-2],可用两个变量a, b分别存储dp[i-2], dp[i-1],迭代更新; - 核心:只保留需要的前序状态,舍弃无用的历史状态。
二、蓝桥杯高频一维 DP 题型与模板
一维 DP 是蓝桥杯最基础、考频最高的 DP 类型,状态定义为dp[i],仅一个决策维度,适合解决单序列、单阶段决策问题,以下是必考题型的模板和解析。
题型 1:斐波那契数列型(线性递推)
问题特征
状态转移仅依赖前 1/2 个连续的子状态 ,呈线性递推关系,是 DP 的入门题型,蓝桥杯常以爬楼梯、跳台阶为背景考察。
经典例题
爬楼梯:一次可以爬 1 级或 2 级台阶,求爬到第 n 级台阶的不同方法数。
解题步骤
- 状态定义:
dp[i]表示爬到第 i 级台阶的方法数; - 初始状态:
dp[1] = 1(1 级台阶 1 种方法),dp[2] = 2(2 级台阶 2 种方法); - 转移方程:
dp[i] = dp[i-1] + dp[i-2](最后一步爬 1 级 / 2 级,由前 i-1 或 i-2 级推导); - 最终答案:
dp[n]。
Python 模板(含空间优化)
python
# 基础版:空间O(n)
def climbStairs(n):
if n <= 2:
return n
dp = [0] * (n + 1)
dp[1], dp[2] = 1, 2
for i in range(3, n + 1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
# 优化版:空间O(1)(蓝桥杯推荐)
def climbStairs(n):
if n <= 2:
return n
a, b = 1, 2 # a=dp[i-2], b=dp[i-1]
for i in range(3, n + 1):
a, b = b, a + b
return b
题型 2:最大子序和(子序列型)
问题特征
求数组中连续子序列 的最优解(最大和 / 最小和),状态转移依赖前一个状态的决策(选 / 不选当前元素),蓝桥杯常直接考察或结合其他考点。
经典例题
最大子序和:给定一个整数数组,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
解题步骤
- 状态定义:
dp[i]表示以第 i 个元素结尾的连续子数组的最大和; - 初始状态:
dp[0] = nums[0](以第一个元素结尾的子数组和为自身); - 转移方程:
dp[i] = max(nums[i], dp[i-1] + nums[i])(选:与前一个子数组拼接;不选:以当前元素为新子数组起点); - 最终答案:
max(dp)(遍历所有结尾的子数组,取最大值)。
Python 模板(含空间优化)
python
# 基础版:空间O(n)
def maxSubArray(nums):
n = len(nums)
dp = [0] * n
dp[0] = nums[0]
for i in range(1, n):
dp[i] = max(nums[i], dp[i-1] + nums[i])
return max(dp)
# 优化版:空间O(1)(蓝桥杯推荐)
def maxSubArray(nums):
pre = nums[0] # 存储dp[i-1]
res = pre # 存储全局最大值
for i in range(1, len(nums)):
pre = max(nums[i], pre + nums[i])
res = max(res, pre)
return res
题型 3:打家劫舍(间隔选择型)
问题特征
从序列中选择元素,不能选择相邻元素 ,求最优解(最大和 / 最大价值),蓝桥杯常以打家劫舍、取数游戏为背景考察。
经典例题
打家劫舍:沿街有一排房屋,每个房屋有一定现金,不能偷相邻的房屋,求能偷到的最大现金数。
解题步骤
- 状态定义:
dp[i]表示前 i 个房屋能偷到的最大现金数; - 初始状态:
dp[0] = 0,dp[1] = nums[0](1 个房屋只能偷它); - 转移方程:
dp[i] = max(dp[i-1], dp[i-2] + nums[i-1])(不偷第 i 个:取前 i-1 个的解;偷第 i 个:取前 i-2 个的解 + 当前房屋现金); - 最终答案:
dp[n](n 为房屋总数)。
Python 模板(含空间优化)
python
# 基础版:空间O(n)
def rob(nums):
n = len(nums)
if n == 0:
return 0
dp = [0] * (n + 1)
dp[1] = nums[0]
for i in range(2, n + 1):
dp[i] = max(dp[i-1], dp[i-2] + nums[i-1])
return dp[n]
# 优化版:空间O(1)(蓝桥杯推荐)
def rob(nums):
if not nums:
return 0
a, b = 0, nums[0] # a=dp[i-2], b=dp[i-1]
for num in nums[1:]:
a, b = b, max(b, a + num)
return b
三、蓝桥杯高频二维 DP 题型与模板
二维 DP 是蓝桥杯中档题核心考点 ,状态定义为dp[i][j],有两个决策维度,适合解决双序列、二维网格、多条件决策问题,以下是必考题型的模板和解析,覆盖 90% 的蓝桥杯二维 DP 考题。
题型 1:二维网格最短路径和(网格型 DP)
问题特征
在二维矩阵 / 网格 中,从一个点走到另一个点(仅能上下 / 左右 / 斜向走,蓝桥杯多为向右 / 向下),求路径的最优解(最短和 / 最长和 / 方案数),是蓝桥杯最常考的二维 DP 题型。
经典例题
最小路径和:给定一个非负整数的 m x n 网格,从左上角走到右下角,仅能向右或向下走,求路径上的数字之和的最小值。
解题步骤
- 状态定义:
dp[i][j]表示从左上角走到第 i 行第 j 列的最小路径和; - 初始状态:
- 第一行:只能从左边走,
dp[0][j] = dp[0][j-1] + grid[0][j]; - 第一列:只能从上面走,
dp[i][0] = dp[i-1][0] + grid[i][0];
- 第一行:只能从左边走,
- 转移方程:
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j](从上面 / 左边走,取最小值 + 当前网格值); - 最终答案:
dp[m-1][n-1](网格索引从 0 开始)。
Python 模板(含空间优化)
python
# 基础版:空间O(mn)
def minPathSum(grid):
m, n = len(grid), len(grid[0])
# 初始化dp数组
dp = [[0]*n for _ in range(m)]
dp[0][0] = grid[0][0]
# 初始化第一行
for j in range(1, n):
dp[0][j] = dp[0][j-1] + grid[0][j]
# 初始化第一列
for i in range(1, m):
dp[i][0] = dp[i-1][0] + grid[i][0]
# 状态转移
for i in range(1, m):
for j in range(1, n):
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
return dp[m-1][n-1]
# 优化版:空间O(n)(用一维数组替代二维,蓝桥杯推荐)
def minPathSum(grid):
m, n = len(grid), len(grid[0])
dp = [0] * n
# 初始化第一行
dp[0] = grid[0][0]
for j in range(1, n):
dp[j] = dp[j-1] + grid[0][j]
# 状态转移
for i in range(1, m):
# 初始化当前行第一列
dp[0] += grid[i][0]
for j in range(1, n):
dp[j] = min(dp[j], dp[j-1]) + grid[i][j]
return dp[-1]
题型 2:01 背包问题(背包型 DP,蓝桥杯重中之重)
背包问题是蓝桥杯DP 的核心考点 ,分为01 背包、完全背包、多重背包 ,其中01 背包是基础,完全背包由 01 背包变形而来,多重背包考频较低,以下重点讲解 01 背包和完全背包。
子题型 1:01 背包(每个物品仅能选一次)
问题特征
有 N 个物品,每个物品有重量 w [i]和价值 v [i] ,一个容量为 V 的背包,每个物品最多选一次 ,求背包能装的最大价值。
解题步骤
- 状态定义:
dp[i][j]表示前 i 个物品,背包容量为 j 时,能装的最大价值; - 初始状态:
dp[0][j] = 0(0 个物品,价值为 0),dp[i][0] = 0(容量为 0,价值为 0); - 转移方程:
- 不选第 i 个物品:
dp[i][j] = dp[i-1][j]; - 选第 i 个物品(需容量≥w [i]):
dp[i][j] = dp[i-1][j-w[i]] + v[i]; - 最终:
dp[i][j] = max(不选, 选);
- 不选第 i 个物品:
- 最终答案:
dp[N][V]。
Python 模板(含空间优化,蓝桥杯必考)
空间优化核心 :二维 dp 可优化为一维数组 dp [j] ,容量从后往前遍历 (避免重复选择同一物品),空间复杂度从O(NV)优化为O(V),是蓝桥杯必写优化!
python
# 01背包优化版:一维数组+逆序遍历,空间O(V)(蓝桥杯推荐)
def zero_one_knapsack(V, w, v):
n = len(w)
dp = [0] * (V + 1) # dp[j]表示容量j的背包的最大价值
for i in range(n): # 遍历每个物品
# 逆序遍历容量,避免重复选同一物品
for j in range(V, w[i]-1, -1):
dp[j] = max(dp[j], dp[j - w[i]] + v[i])
return dp[V]
# 使用示例
V = 5 # 背包容量
w = [2, 3, 4] # 物品重量
v = [3, 4, 5] # 物品价值
print(zero_one_knapsack(V, w, v)) # 输出7(选第一个和第二个物品,2+3=5容量,3+4=7价值)
子题型 2:完全背包(每个物品可选无限次)
问题特征
与 01 背包唯一区别:每个物品可选无限次,蓝桥杯常以 ** 凑零钱、爬楼梯(进阶)** 为背景考察。
解题步骤
与 01 背包基本一致,仅状态转移的容量遍历方向不同。
Python 模板(优化版,蓝桥杯必考)
空间优化核心 :一维数组dp[j],容量从前往后遍历(允许重复选择同一物品),是与 01 背包的唯一区别!
python
# 完全背包优化版:一维数组+正序遍历,空间O(V)(蓝桥杯推荐)
def complete_knapsack(V, w, v):
n = len(w)
dp = [0] * (V + 1)
for i in range(n): # 遍历每个物品
# 正序遍历容量,允许重复选同一物品
for j in range(w[i], V + 1):
dp[j] = max(dp[j], dp[j - w[i]] + v[i])
return dp[V]
# 经典例题:凑零钱(求凑成总金额的最少硬币数)
def coinChange(coins, amount):
# 初始化dp为无穷大,表示不可达
dp = [float('inf')] * (amount + 1)
dp[0] = 0 # 金额0需要0个硬币
for coin in coins:
for j in range(coin, amount + 1):
dp[j] = min(dp[j], dp[j - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
题型 3:最长公共子序列(LCS,双序列型)
问题特征
给定两个字符串 / 序列,求它们的最长公共子序列(子序列可不连续),是蓝桥杯双序列 DP 的代表题型,常直接考察或结合字符串编辑距离。
解题步骤
- 状态定义:
dp[i][j]表示字符串 s1 的前 i 个字符和字符串 s2 的前 j 个字符的最长公共子序列长度; - 初始状态:
dp[0][j] = 0,dp[i][0] = 0(一个字符串为空,公共子序列长度为 0); - 转移方程:
- 若 s1 [i-1] == s2 [j-1](当前字符相同):
dp[i][j] = dp[i-1][j-1] + 1; - 若 s1 [i-1] != s2 [j-1](当前字符不同):
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
- 若 s1 [i-1] == s2 [j-1](当前字符相同):
- 最终答案:
dp[len(s1)][len(s2)]。
Python 模板
python
def longestCommonSubsequence(s1, s2):
m, n = len(s1), len(s2)
# 初始化dp数组,多开一行一列方便处理边界
dp = [[0]*(n+1) for _ in range(m+1)]
for i in range(1, m+1):
for j in range(1, n+1):
if s1[i-1] == s2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return dp[m][n]
# 使用示例
s1 = "abcde"
s2 = "ace"
print(longestCommonSubsequence(s1, s2)) # 输出3(ace)
四、蓝桥杯 DP 实战技巧与避坑指南
1. 状态定义的核心技巧
- 从问题出发 :让 dp 数组的含义直接对应问题的解,避免复杂的状态转换;
- 关注 "结尾 / 前 i 个" :一维 DP 常定义为
以i结尾或前i个,二维 DP 常定义为前i个+前j个/第i行第j列; - 维度简化:能定义一维的绝不定义二维,减少代码量和空间复杂度。
2. 蓝桥杯高频避坑点
(1)数组索引越界
- 原因:蓝桥杯题目中元素编号常从 1 开始,而 Python 列表索引从 0 开始;
- 解决:初始化 dp 数组时多开一个位置(如前 n 个元素,dp 数组长度为 n+1),避免索引错位。
(2)初始状态赋值错误
- 问题:最值问题中初始状态赋值为 0,导致负数解错误(如最大子序和含负数);
- 解决:
- 求最大值 :非边界初始状态赋值为
-float('inf'); - 求最小值 :非边界初始状态赋值为
float('inf'); - 计数问题:初始状态赋值为 0,不可达状态赋值为 0(或根据题意)。
- 求最大值 :非边界初始状态赋值为
(3)背包问题遍历方向错误
- 01 背包必须逆序遍历容量,否则会重复选择同一物品;
- 完全背包必须正序遍历容量,否则无法重复选择同一物品;
- 这是蓝桥杯背包问题最常见的丢分点,务必牢记!
(4)忽略空间限制
- 蓝桥杯部分题目空间限制严格(如 128MB),二维 DP 数组可能超出空间;
- 解决:优先使用空间优化版(一维数组 / 滚动变量),尤其是背包问题、网格 DP。
(5)递归深度超限(记忆化递归)
-
Python 默认递归深度为 1000,若问题规模超过 1000(如 n=1e4),递归会报错;
-
解决:① 改用自底向上的迭代法 (推荐);② 手动扩大递归深度:
pythonimport sys sys.setrecursionlimit(10**6) # 扩大到1e6
3. 蓝桥杯 DP 刷题优先级
根据考频从高到低刷题,高效备战:
- 基础一维 DP:爬楼梯、最大子序和、打家劫舍;
- 背包问题:01 背包、完全背包(凑零钱、找方案数);
- 二维网格 DP:最短路径和、不同路径(求方案数);
- 双序列 DP:最长公共子序列、最长回文子串;
- 进阶 DP:状态压缩 DP(如状压 01 背包)、数位 DP(蓝桥杯国赛偶尔考)。
4. Python 优化 DP 运行速度的技巧
蓝桥杯 Python 的时间限制较严格(通常 1s),DP 题若数据量较大(如 1e4、1e5),需优化运行速度:
- 用列表替代字典:dp 的存储优先用列表,字典的查找和赋值效率远低于列表;
- 减少循环内的计算:将循环内的重复计算提取到外部(如提前计算 len (nums));
- 用局部变量替代全局变量:Python 局部变量的访问速度比全局变量快;
- 避免不必要的嵌套:尽量简化循环结构,减少嵌套层数。
五、总结
动态规划的核心不是死记模板,而是理解解题框架 ------状态定义→初始状态→转移方程→最终答案 ,所有题型都是这个框架的具体应用。蓝桥杯的 DP 题难度适中,以基础和中档题为主,极少出现难题,只要熟记核心题型的模板,掌握空间优化技巧,避开常见坑点,就能轻松拿下 DP 的分数。
备考建议:先刷透经典题型,再做蓝桥杯真题,将模板内化为自己的思路,做到能根据题目快速拆解状态、推导转移方程,这是解决 DP 问题的关键。