分享丨【题单】动态规划(入门/背包/状态机/划分/区间/状压/数位/树形/数据结构优化)
By 灵茶山艾府
最近编辑于 2024-07-01
HX注
恕我直言, 这个价值三千七百万!
前缀和优化 DP【力扣周赛 410】 43:28 开始, 聊一聊怎么刷题, 其中提到了dp (前面有手把手指导记忆化1:1翻译成dp的步骤)
学习dp的重点, 就是锻炼
寻找子问题
的能力, 剩下的都是代码能力上的东西!
前言
掌握动态规划(DP)是没有捷径的,咱们唯一能做的,就是投入时间猛猛刷题。好比学数学,只看书看视频而不做习题,是不能说学会的。
我能做的,是帮你节省找题的时间,并把这些题分类整理好。有着相同套路的题,一起做效率会更高,也更能领悟到 DP 的精髓。所以推荐按照专题刷。
题目已按照难度分排序(右侧数字为难度分)。如果遇到难度很大,题解都看不懂的题目,建议直接跳过,二刷的时候再来尝试。
一、入门 DP
记忆化搜索是新手村神器(甚至可以用到游戏后期),推荐先看 动态规划入门:从记忆化搜索到递推。
但记忆化搜索并不是万能的,某些题目只有写成递推,才能结合数据结构等来优化时间复杂度,多数题目还可以优化空间复杂度。所以尽量在写完记忆化搜索后,把递推的代码也写一下。熟练之后直接写递推也可以。
§1.1 爬楼梯
- 70. 爬楼梯(题解)
- 746. 使用最小花费爬楼梯(题解)
- 377. 组合总和 Ⅳ 本质是爬楼梯,相当于每次往上爬 步
- 2466. 统计构造好字符串的方案数 1694
- 2266. 统计打字方案数 1857 (线性dp 乘法原理)
- 2533. 好二进制字符串的数量(会员题)
§1.2 打家劫舍
- 198. 打家劫舍 ~1500
- 740. 删除并获得点数 ~1600 (左不能, 右不能, 就是可转化为打家劫舍~~(值域?)~~)
- 2320. 统计放置房子的方式数 1608
- 213. 打家劫舍 II ~1650
- 3186. 施咒的最大总伤害 ~1850 (对cpp不友好(卡常?!); 值域打家劫舍)
通用套路: # 不能选择相邻(a[i - 1], a[i + 1]), 则分: 不选, 选 两种情况
对于选择了a[i]就不能选择a[i] - 2 ,a[i] - 1 ,a[i] + 1 或者 a[i] + 2
的同理: # 不选, 选(其中a[j - 1] < arr[i] - 2
)
对于值域做法, 可以先使用哈希表统计, 映射到数组, 再通过索引做记忆化/dp的参数
§1.3 最大子数组和 (最大子段和)
有两种做法:
-
定义状态 表示以 结尾的最大子数组和,不和 左边拼起来就是 , 和 左边拼起来就是 , 取最大值就得到了状态转移方程 , 答案为 。这个做法也叫做 算法。
-
用前缀和解决,具体见 我的题解。
- 53. 最大子数组和 ~1400
- 2606. 找到最大开销的子字符串 1422
- 1749. 任意子数组和的绝对值的最大值 1542
- [学习] 1191. K 次串联后最大子数组之和 1748
- [学习] 918. 环形子数组的最大和 1777
- [学习] 2321. 拼接数组的最大分数 1791
思维扩展:
- 152. 乘积最大子数组 (提示: 前一个数是正/负两种状态)
二、网格图 DP
对于一些二维 DP(例如背包、最长公共子序列),如果把 DP 矩阵画出来,其实状态转移可以视作在网格图上的移动。所以在学习相对更抽象的二维 DP 之前,做一些形象的网格图 DP 会让后续的学习更轻松(比如 0-1 背包的空间优化写法为什么要倒序遍历)。
§2.1 基础
- LCR 166. 珠宝的最高价值
- 62. 不同路径
- 63. 不同路径 II
- 64. 最小路径和
- 120. 三角形最小路径和
- 931. 下降路径最小和 1573
- 2684. 矩阵中移动的最大次数 1626
- 2304. 网格中的最小路径代价 1658
- 1289. 下降路径最小和 II 1697
§2.2 进阶
- 1594. 矩阵的最大非负积 1807 要求最后取模!, 思路同: 152. 乘积最大子数组
- 1301. 最大得分的路径数目 1853
- 2435. 矩阵中和能被 K 整除的路径 1952 (套路: 把路径和模 的结果当成一个扩展维度)
- 174. 地下城游戏 (正难则反dp)
- 329. 矩阵中的最长递增路径 (记忆化 / 预处理 + 拓扑排序)
- 2328. 网格图中递增路径的数目 2001 (同 329)
- [学习] 2267. 检查是否有合法括号字符串路径 2085 (括号匹配固定套路: 任何时刻左括号数量 >= 右括号数量, 可定义 左括号 - 右括号, 或者说 左括号: ++c, 右括号: --c; c >= 0 (任何时刻), c == 1, (最后一个, 并且最后为 右括号(不包括它)); 剪枝: 必须保证: 左右括号数 % 2 == 0)
- [学习] 1937. 扣分后的最大得分 2106 (写出 dp 式子, 拆开绝对值, 分类讨论(化简式子); 奇妙的for方式!)
- [学习] 1463. 摘樱桃 II
- [学习] 741. 摘樱桃
- 2510. 检查是否有路径经过相同数量的 0 和 1(会员题)
三、背包
讲解:0-1 背包 完全背包
§3.1 0-1 背包
每个物品只能选一次。
- 2915. 和为目标值的最长子序列的长度 1659
- 416. 分割等和子集
- 494. 目标和 (有点水平这题qwq)
- 2787. 将一个数字表示成幂的和的方案数 1818
- 3180. 执行操作可获得的最大总奖励 I 1849 (难难难~ 不会... 价值为体积类背包?)
- 474. 一和零(二维)(蒙的状态转移方程)
- [学习] 1049. 最后一块石头的重量 II 2092 (脑筋急转弯: 把所有的 +- 提出来: 就是
价值为体积类背包求 下取整sum/2
容量的最大价值, 然后 sum - 2 * f[]) - 1774. 最接近目标价格的甜点成本 (记忆化更好, 更少无用状态)
- [学习] 879. 盈利计划 2204 (初始化问题, 状态定义与边界)
- 3082. 求出所有子序列的能量和 2242
- 956. 最高的广告牌 2381 (定义状态为高度差值, 对于一方的高度可以 +1/-1/0, 注意身份切换)
- 2518. 好分区的数目 2415
- 2742. 给墙壁刷油漆 2425
- LCP 47. 入场安检
- 2291. 最大股票收益(会员题)
- 2431. 最大限度地提高购买水果的口味(会员题)
§3.2 完全背包
物品可以重复选,无个数限制。
- 322. 零钱兑换
- 518. 零钱兑换 II
- 279. 完全平方数
- 1449. 数位成本和为目标值的最大数字 1927 (小心字符串的max是单纯的字典序的)
§3.3 多重背包
物品可以重复选,有个数限制。
注:力扣上只有求方案数的题目。
- 2585. 获得分数的方法数 1910 (注意, 同一类题目是完全相同的, 因此 枚举题目数量得在最内层for)
- 2902. 和带限制的子多重集合的数目 2759
§3.4 分组背包
同一组内的物品至多/恰好选一个。
- 1155. 掷骰子等于目标和的方法数 1654 (前缀和才可以滚动压缩)
- [学习] 1981. 最小化目标值与所选元素的差 2010 (没有绝对值我可能还会... dp二进制优化?!)
- 2218. 从栈中取出 K 个硬币的最大面值和 2158
四、经典线性 DP
§4.1 最长公共子序列(LCS)
讲解:最长公共子序列 编辑距离
一般定义 表示对 的求解结果。
- 1143. 最长公共子序列
- 583. 两个字符串的删除操作
- 712. 两个字符串的最小 ASCII 删除和
- 72. 编辑距离
- [学习] 97. 交错字符串 (定义 s1[0:i] s2[0:j] 为 f[i][j] 可以凑出 s3[0: i + j])
- [学习] 115. 不同的子序列 (状态定义正确, 但是初始化没有, 状态转移不对!)
- 1035. 不相交的线 1806
- 1458. 两个子序列的最大点积 1824 (学到了一种: 不能用0来规避越界的初始化, 得像官解一样,先下手为强
int t = f[i][j] = nums1[i] * nums2[j];
) - 1092. 最短公共超序列 1977 (用string dp 再怎么优化也是超内存(过了但不是正解), 正解是改为dp长度, 然后双指针构造字符串(这个并不是很会...))
- 1639. 通过给定词典构造目标字符串的方案数 2082 (记忆化, 但是 , 预处理同一列字符个数, 可以有 )
- 44. 通配符匹配 (
@cache
) - 10. 正则表达式匹配 (
@cache
)
§4.2 最长递增子序列(LIS)
讲解:最长递增子序列
做法有很多:
- 枚举选哪个(见讲解)。
- 贪心+二分(见讲解)。
- 计算 和把 排序后的数组 的最长公共子序列。
- 数据结构优化(见 2407 题)。
- 300. 最长递增子序列
- 673. 最长递增子序列的个数
- 2826. 将三个组排序 1721 (也可以状态机dp)
- 1671. 得到山形数组的最少删除次数 1913 (前后缀分解)
- 1964. 找出到每个位置为止最长的有效障碍赛跑路线 1933 (裸题, 但是需要二分log优化~)
- 2111. 使数组 K 递增的最少操作次数 1941 (转换为互不相交子序列, (注意可能有子序列长度不一致!) 二分log优化dp~)
- 1626. 无矛盾的最佳球队 2027 (按年龄排序转换~)
- 354. 俄罗斯套娃信封问题(二维 LIS)(把握好排序) 如何排序 & 如何扩展到高维度情况
- 1691. 堆叠长方体的最大高度 2172 (把握好排序)
- 2247
- 2407. 最长递增子序列 II 2280 (值域线段树优化dp...)
- 1187. 使数组严格递增 2316
- 1713. 得到子序列的最少操作次数 2351
思维扩展:
- 368. 最大整除子集 (有点妙~)
思考题:
给定整数 ,构造一个数组 ,使得 恰好有 个最长递增子序列。
五、状态机 DP
讲解:状态机 DP
一般定义 表示前缀 在状态 下的最优值。一般 都很小。代表题目是「买卖股票」系列。
注: 某些题目做法不止一种,除了状态机 DP 以外,也有前后缀分解的做法。
- 121. 买卖股票的最佳时机
- 122. 买卖股票的最佳时机 II
- 188. 买卖股票的最佳时机 IV
- 309. 买卖股票的最佳时机含冷冻期
- 714. 买卖股票的最佳时机含手续费
- 1493. 删掉一个元素以后全为 1 的最长子数组 1423
- 1395. 统计作战单位数
- 2745. 构造最长的新字符串 1607
- 2222. 选择建筑的方案数 1657
- 376. 摆动序列 做到 时间
- 1567. 乘积为正数的最长子数组长度 1710
- 2708. 一个小组的最大实力值 做到 时间
- 2826. 将三个组排序 1721
- 2786. 访问数组中的位置使分数最大 1733
- 1262. 可被三整除的最大和 1762
- 1363. 形成三的最大倍数 (dp简单, 复原出字符串难qwq)
- 1911. 最大子序列交替和 1786
- 2771. 构造最长非递减子数组 1792
- 1186. 删除一次得到子数组最大和 1799
- 1594. 矩阵的最大非负积 1807
- 3196. 最大化子数组的总成本 ~1850 也有划分型 DP 做法
- 935. 骑士拨号器 (同类状态可以乘算!)
- 1537. 最大得分 1961 (转换为图dp / 双指针)
- 2919. 使数组变美的最小增量运算数 2031 (还没有搞懂)
- 801. 使序列递增的最小交换次数 2066 (定义换/不换)
- 1955. 统计特殊子序列的数目 2125
- 3068. 最大节点价值之和 2268
- LCP 19. 秋叶收藏集
- 276. 栅栏涂色(会员题)
- 1746. 经过一次操作后的最大子数组和(会员题)
- 2036. 最大交替子数组和(会员题)
- 2361. 乘坐火车路线的最少费用(会员题)
六、划分型 DP
§6.1 判定能否划分
一般定义 表示长为 的前缀 能否划分。
枚举最后一个子数组的左端点 ,从 转移到 ,并考虑 是否满足要求。
§6.2 计算划分最优值
计算最少(最多)可以划分出多少段、最优划分得分等。
一般定义 表示长为 的前缀 在题目约束下,分割出的最少(最多)子数组个数(或者定义成分割方案数)。
枚举最后一个子数组的左端点 ,从 转移到 ,并考虑 对最优解的影响。
- 132. 分割回文串 II (有预处理回文子串的dp)
- 2707. 字符串中的额外字符 1736
- 3196. 最大化子数组的总成本 ~1850 也有状态机 DP 做法
- 2767. 将字符串分割为最少的美丽子字符串 1865
- 91. 解码方法
- 639. 解码方法 II
- LCR 165. 解密数字
- 1416. 恢复数组 1920
- 2472. 不重叠回文子字符串的最大数目 2013 (中心扩展 + DP (我暴力判断回文的~, 两千个'a'那个样例无法通过))
- 1105. 填充书架 2014 (有难度的处理和状态转移思考, 从递归开始好思考~)
- 2547. 拆分数组的最小代价 2020 (我甚至使用滑动窗口预处理,题解都没有需要..可以线段树优化qwq..)
- 2430. 对字母串可执行的最大删除数 2102
- 2463. 最小移动总距离 2454
- 2977. 转换字符串的最小成本 II 2696
- 2052. 将句子分隔成行的最低成本(会员题)
- 2464. 有效分割中的最少子数组数目(会员题)
§6.3 约束划分个数
将数组分成 (恰好/至多) 个连续子数组,计算与这些子数组有关的最优值。
一般定义 表示将长为 的前缀 分成 个连续子数组所得到的最优解。
枚举最后一个子数组的左端点 ,从 转移到 ,并考虑 对最优解的影响。
- 410. 分割数组的最大值 (qwq)
- 1043. 分隔数组以得到最大和 1916
- 1745. 分割回文串 IV 1925
- 813. 最大平均值和的分组 1937
- 1278. 分割回文串 iii 1979
- 1335. 工作计划的最低难度 2035
- 1473. 粉刷房子 iii 2056 (有点难度qwq..)
- 1478. 安排邮筒 2190
- 1959. K 次调整数组大小浪费的最小总空间 2310 *转换
- 2478. 完美分割的方案数 2344
- 3077. K 个不相交子数组的最大能量值 2557
- 2911. 得到 K 个半回文串的最少修改次数 2608
- 3117. 划分数组得到最小的值之和 2735
§6.4 不相交区间
- 2830. 销售利润最大化 1851
- 2008. 出租车的最大盈利 1872
- 1235. 规划兼职工作 2023 也可以用堆 (二分优化)
- 1751. 最多可以参加的会议数目 II 2041
七、其他线性 DP
§7.1 一维
发生在前缀/后缀之间的转移,例如从 转移到 ,或者从 转移到 。
- 2944. 购买水果需要的最少金币数 1709
- 2140. 解决智力问题 1709
- 983. 最低票价 1786
- 2901. 最长相邻不相等子序列 II 1899 (拼结果比较妙! 我是暴力的, 0x3f好像是使用一个from来记录, 然后可以从最后一个找到它的上一个, 类似于父节点. 从而还原!)
- 3144. 分割字符频率相等的最少子字符串 1917 (很妙的计算
平衡字符串
的方法) - 871. 最低加油次数 2074 (贪心堆...dp不会)
- 2896. 执行操作使两个字符串相等 2172
- 2167. 移除所有载有违禁货物车厢所需的最少时间 2219
- 2188. 完成比赛的最少时间 2315
- 1259. 不相交的握手(会员题)
§7.2 特殊子序列
比较特殊的一类题型,递推比记忆化搜索好写。
- 2501. 数组中最长的方波 1480
- 1218. 最长定差子序列 1597
- 1027. 最长等差数列 1759
- 3202. 找出有效子序列的最大长度 II ~1850
- 873. 最长的斐波那契子序列的长度 1911 (我的纯哈希超时了, 还得像题解那样改为索引+vector的/不然就unordered_set暴力)
- 446. 等差数列划分 II - 子序列 (学习状态!: 定义i结尾, 公差为d的子序列个数为f[i][j])
- 1048. 最长字符串链
- 3098. 求出所有子序列的能量和 2553
§7.3 矩阵快速幂优化
部分题目由于数据范围小,也可以用线性 DP。
- 70. 爬楼梯
- 509. 斐波那契数
- 1137. 第 N 个泰波那契数
- 1220. 统计元音字母序列的数目
- 552. 学生出勤记录 II
- 790. 多米诺和托米诺平铺
- 2851. 字符串转换 2858
- 2912. 在网格上移动到目的地的方法数(会员题)
§7.4 子矩形
- 3148. 矩阵中的最大得分 1820
- 221. 最大正方形
- 1277. 统计全为 1 的正方形子矩阵
- 2088. 统计农场中肥沃金字塔的数目 2105
- 3197. 包含所有 1 的最小矩形面积 II 做法
§7.5 多维
- 2400. 恰好移动 k 步到达某一位置的方法数目 1751
- 2370. 最长理想子序列 1835
- 3176. 求出最长好子序列 I 1849
- 1269. 停在原地的方案数 1854
- 3122. 使矩阵满足条件的最少操作次数 1905
- 576. 出界的路径数
- 403. 青蛙过河
- 1223. 掷骰子模拟 2008
- 1320. 二指输入的的最小距离 2028
- 1575. 统计所有可行路径 2055
- 3154. 到达第 K 级台阶的方案数 2071
- 2318. 不同骰子序列的数目 2090
- 2209. 用地毯覆盖后的最少白色砖块 2106
- 1444. 切披萨的方案数 2127
- 1420. 生成数组 2176
- 3193. 统计逆序对的数目 ~2250
- 629. K 个逆序对数组 ~2300
- 1866. 恰有 K 根木棍可以看到的排列数目 2333
- 2312. 卖木头块 2363
- 3177. 求出最长好子序列 II 2365
- 887. 鸡蛋掉落 2377
- 1884. 鸡蛋掉落-两枚鸡蛋
- 1388. 3n 块披萨 2410
- 1900. 最佳运动员的比拼回合 2455
- 1883. 准时抵达会议现场的最小跳过休息次数 2588 避免浮点运算的技巧
- LCP 57. 打地鼠
- 256. 粉刷房子(会员题)
- 265. 粉刷房子 II(会员题)
- 568. 最大休假天数(会员题)
- 1692. 计算分配糖果的不同方式(会员题)
- 2143. 在两个数组的区间中选取数字(会员题)
八、区间 DP
讲解:区间 DP
从数组的左右两端不断缩短,求解关于某段下标区间的最优值。
一般定义 表示下标区间 的最优值。
§8.1 最长回文子序列
- 516. 最长回文子序列
- [超难] 730. 统计不同回文子序列
- 1312. 让字符串成为回文串的最少插入次数 1787
- 1771. 由子序列构造的最长回文串的长度 2182
- 1682. 最长回文子序列 II(会员题)
- (会员题)
- 1246. 删除回文子数组(会员题)
§8.2 其他区间 DP
- 5. 最长回文子串 (马拉车, dp不是最优 => 不好想)
- 3040. 相同分数的最大操作数目 II 1709
- 375. 猜数字大小 II
- 1130. 叶值的最小代价生成树 1919
- 96. 不同的二叉搜索树
- 1770. 执行乘法运算的最大分数 2068
- 1547. 切棍子的最小成本 2116
- 1039. 多边形三角剖分的最低得分 2130
- 1000. 合并石头的最低成本 2423
- 2019. 解出数学表达式的学生分数 2584
- 87. 扰乱字符串
- 312. 戳气球
- 664. 奇怪的打印机
- 546. 移除盒子 同 CF1107E,可能是力扣上最难的 DP
- 471. 编码最短长度的字符串(会员题)
- 3018. 可处理的最大删除操作数 I(会员题)
九、状态压缩 DP(状压 DP)
§9.1 排列型 ① 相邻无关
学习指南:
暴力做法是枚举所有排列,对每个排列计算和题目有关的值,时间复杂度(通常来说)是 O(n⋅n!)\mathcal{O}(n\cdot n!)O(n⋅n!)。可以解决 n≤10n\le 10n≤10 的问题。
状压 DP 可以把时间复杂度(通常来说)优化至 O(n⋅2n)\mathcal{O}(n\cdot 2^n)O(n⋅2n)。可以解决 n≤20n\le 20n≤20 的问题。
一般有两种定义方式:
- 定义 f[S]f[S]f[S] 表示已经排列好的元素(下标)集合为 SSS 时,和题目有关的最优值。通过枚举当前位置要填的元素(下标)来转移。
- 定义 f[S]f[S]f[S] 表示可以选的元素(下标)集合为 SSS 时,和题目有关的最优值。通过枚举当前位置要填的元素(下标)来转移。
注:部分题目由于爆搜+剪枝也能过,难度分仅供参考。
- 526. 优美的排列
- 1879. 两个数组最小的异或值之和 2145
- 2850. 将石头分散到网格图的最少移动次数
- 1947. 最大兼容性评分和
- 1799. N 次操作后的最大分数和
- 2172. 数组的最大与和 2392
- 1066. 校园自行车分配 II(会员题)
- 2992. 自整除排列的数量(会员题)
- 2403. 杀死所有怪物的最短时间(会员题)
§9.2 排列型 ② 相邻相关
一般定义 f[S][i]f[S][i]f[S][i] 表示未选(或者已选)的集合为 SSS,且上一个填的元素(下标)为 时,和题目有关的最优值。通过枚举当前位置要填的元素(下标)来转移。
时间复杂度(通常来说)是 O(n2⋅2n)\mathcal{O}(n^2\cdot 2^n)O(n2⋅2n)。
- 996. 正方形数组的数目 1932
- 2741. 特别的排列 2021
- 1681. 最小不兼容性 2390
- 3149. 找出分数最低的排列 2642
§9.3 旅行商问题(TSP)
本质上就是排列型 ②。
- 943. 最短超级串 2186
- 847. 访问所有节点的最短路径 2201
- LCP 13. 寻宝
- 2247. K 条高速公路的最大旅行费用(会员题)
§9.4 枚举子集的子集
一般定义 f[S]f[S]f[S] 表示未选(或者已选)的集合为 SSS 时,和题目有关的最优值。通过枚举 SSS(或者 SSS 的补集 ∁US\complement_US∁US)的子集来转移。
时间复杂度(通常来说)是 O(3n)\mathcal{O}(3^n)O(3n),证明见 题解。
值得注意的是,枚举子集的子集还可以用「选或不选」来做,对于存在无效状态的情况,可以做到更优的时间复杂度。具体见 1349 题解 最后的写法。
- 2305. 公平分发饼干 1887
- 1986. 完成任务的最少工作时间段 1995
- 1494. 并行课程 II 2082
- 1723. 完成所有工作的最短时间 2284
- 1655. 分配重复整数 2307
- 1349. 参加考试的最大学生数 2386
- 1681. 最小不兼容性 2390 有 O(n2⋅2n)\mathcal{O}(n^2\cdot 2^n)O(n2⋅2n) 做法
- 2572. 无平方子集计数 2420
- 1994. 好子集的数目 2465
- LCP 04. 覆盖
- LCP 53. 守护太空城
- 465. 最优账单平衡(会员题)
- 2152. 穿过所有点的所需最少直线数量(会员题)
§9.5 其他状压 DP
- 698. 划分为k个相等的子集
- 1411. 给 N x 3 网格图涂色的方案数 1845
- 2002. 两个回文子序列长度的最大乘积 1869
- 473. 火柴拼正方形
- 1931. 用三种不同颜色为网格涂色 2170
- 1125. 最小的必要团队 2251
- 1434. 每个人戴不同帽子的方案数 2273
- 464. 我能赢吗
- 691. 贴纸拼词
- 1595. 连通两组点的最小成本 2538
- 1815. 得到新鲜甜甜圈的最多组数 2559
- 1659. 最大化网格幸福感 2655
- LCP 69. Hello LeetCode!
- LCP 76. 魔法棋盘
- LCP 82. 万灵之树
- 351. 安卓系统手势解锁(会员题)
- 2184. 建造坚实的砖墙的方法数(会员题)
十、数位 DP
- 2719. 统计整数数目
- 788. 旋转数字
- 902. 最大为 N 的数字组合 1990
- 233. 数字 1 的个数
- 面试题 17.06. 2 出现的次数
- 600. 不含连续 1 的非负整数
- 2376. 统计特殊整数 2120
- 1012. 至少有 1 位重复的数字 2230
- 357. 统计各位数字都不同的数字个数
- 3007. 价值和小于等于 K 的最大数字 2258 做法不止一种
- 2827. 范围中美丽整数的数目 2324
- 2999. 统计强大整数的数目 2351
- 2801. 统计范围内的步进数字数目 2367
- 1397. 找到所有好字符串 2667
- 1215. 步进数(会员题)
- 1067. 范围内的数字计数(会员题)
- 3032. 统计各位数字都不同的数字个数 II(会员题)
- 1742. 盒子中小球的最大数量 *非暴力做法 枚举数位和+DP
- 2843. 统计对称整数的数目 *非暴力做法
十一、数据结构优化 DP
§11.1 前缀和优化 DP
- 2327. 知道秘密的人数 1894
- 1997. 访问完所有房间的第一天 2260
- 2478. 完美分割的方案数 2344
- 837. 新 21 点 2350
- 2463. 最小移动总距离 2454
- 629. K 个逆序对数组
- 1977. 划分数字的方案数 2817
- 3130. 找出所有稳定的二进制数组 II 2825
§11.2 单调栈优化 DP
前置题单:单调栈(矩形系列/字典序最小/贡献法)
- 1335. 工作计划的最低难度 2035
- 2866. 美丽塔 II 2072
- 2617. 网格图中最少访问的格子数 2582
- 2355. 你能拿走的最大图书数量(会员题)
§11.3 单调队列优化 DP
一般用来维护一段转移来源的最值。
- 前提:区间右端点变大时,左端点也在变大(同滑动窗口)。
- 转移前,去掉队首无用数据。
- 计算转移(直接从队首转移)。
- 把数据(一般是 )插入队尾前,去掉队尾无用数据。
- 2944. 购买水果需要的最少金币数 1709 可以用单调队列优化到 O(n)\mathcal{O}(n)O(n)
- 1696. 跳跃游戏 VI 1954
- 1425. 带限制的子序列和 2032
- 375. 猜数字大小 II 可以用单调队列优化到 O(n2)\mathcal{O}(n^2)O(n2)
- 1687. 从仓库到码头运输箱子 2610
- 2463. 最小移动总距离 做到 O(nm)\mathcal{O}(nm)O(nm)(注:还有 O((n+m)log(n+m))\mathcal{O}((n+m)\log(n+m))O((n+m)log(n+m)) 的反悔贪心做法)
- 3117. 划分数组得到最小的值之和 2735
- 2945. 找到最大非递减数组的长度 2943
- 2969. 购买水果需要的最少金币数 II(会员题)
§11.4 树状数组/线段树优化 DP
- 1626. 无矛盾的最佳球队 2027
- 2407. 最长递增子序列 II 2280
- 2770. 达到末尾下标所需的最大跳跃次数 见我题解下的 评论
- 2926. 平衡子序列的最大和 2448
- 2916. 子数组不同元素数目的平方和 II 2816
§11.5 字典树优化 DP
- 139. 单词拆分
- 140. 单词拆分 II
- 472. 连接词 ~2300
- 2977. 转换字符串的最小成本 II 2696
§11.6 其他优化 DP
- 2713. 矩阵中严格递增的单元格数 2387
- 3181. 执行操作可获得的最大总奖励 II 2688 bitset 优化
- LCP 59. 搭桥过河
- 2263. 数组变为有序的最小操作次数(会员题)Slope Trick
十二、树形 DP
注:可能有同学觉得树形 DP 没有重复访问同一个状态(重叠子问题),并不能算作 DP,而是算作普通的递归。这么说也有一定道理,不过考虑到思维方式和 DP 是一样的自底向上,所以仍然叫做树形 DP。此外,如果是自顶向下的递归做法,是存在重叠子问题的,一般要结合记忆化搜索实现。
§12.1 树的直径
讲解:树形 DP:树的直径
- 543. 二叉树的直径
- 124. 二叉树中的最大路径和
- 687. 最长同值路径
- 2246. 相邻字符不同的最长路径 2126
- 3203. 合并两棵树后的最小直径 ~2150
- 1617. 统计子树中城市之间最大距离 2309
- 2538. 最大价值和与最小价值和的差值 2398
- 1245. 树的直径(会员题)
注:求直径也有两次 DFS 的做法。
§12.2 树上最大独立集
- (没有上司的舞会)
- 2646. 最小化旅行的价格总和 2238
- 2378. 选择边来最大化树的得分(会员题)
§12.3 树上最小支配集
讲解:树形 DP:监控二叉树,包含 968 的变形题。
- 968. 监控二叉树 2124
§12.4 换根 DP
也叫二次扫描法。
- 834. 树中距离之和 2197
- 2581. 统计可能的树根数目 2228
- 2858. 可以到达每一个节点的最少边反转次数 2295
- 310. 最小高度树 也可以用拓扑排序做
§12.5 其他树形 DP
- 2925. 在树上执行操作以后得到的最大分数 1940
- 3068. 最大节点价值之和 2268
- 2920. 收集所有金币可获得的最大积分 2351
- 1916. 统计为蚁群构筑房间的不同顺序 2486
- LCP 10. 二叉树任务调度
- LCP 34. 二叉树染色
- LCP 64. 二叉树灯饰
- 2313. 二叉树中得到结果所需的最少翻转次数(会员题)
十三、图 DP
- 787. K 站中转内最便宜的航班 1786
- 1786. 从第一个节点出发到最后一个节点的受限路径数 2079
- 2084
- 1976. 到达目的地的方案数 2095
- 1857. 有向图中最大颜色值 2313
- 1928. 规定时间内到达终点的最小花费 2413
- LCP 07. 传递信息
- 1548. 图中最相似的路径(会员题)
另见【题单】图论算法 中的「全源最短路:Floyd」,本质是多维 DP。
十四、博弈 DP
- 1025. 除数博弈 1435 有数学做法
- 877. 石子游戏 1590 有数学做法
- 486. 预测赢家
- 1510. 石子游戏 IV 1787
- 1690. 石子游戏 VII 1951
- 2027
- 1140. 石子游戏 II 2035
- 1563. 石子游戏 V 2087
- 464. 我能赢吗
- 2440
- 913. 猫和老鼠 2567
- 294. 翻转游戏 II(会员题)
十五、概率/期望 DP
- 688. 骑士在棋盘上的概率
- 837. 新 21 点 2350
- 1467. 两个盒子中球的颜色数相同的概率 2357
- 808. 分汤 2397
- LCR 185. 统计结果概率
- 九坤-04. 筹码游戏
- 1230. 抛掷硬币(会员题)
专题:输出具体方案(打印方案)
注意这些题目和回溯的区别,某些回溯题目要求输出所有方案,这里只要求输出一个。
- 368. 最大整除子集
- 1449. 数位成本和为目标值的最大数字 1927
- 1092. 最短公共超序列 1977
- 943. 最短超级串 2186
- 1125. 最小的必要团队 2251
- 3149. 找出分数最低的排列 2642 字典序最小
- 656. 金币路径(会员题)字典序最小
- 471. 编码最短长度的字符串(会员题)
专题:前后缀分解
部分题目也可以用状态机 DP 解决。
- 42. 接雨水(讲解)
- 拆分成两个 121 题
- 1422. 分割字符串的最大得分 1238
- 2256. 最小平均差 1395
- 1493. 删掉一个元素以后全为 1 的最长子数组 1423
- 845. 数组中的最长山脉 1437 *也可以分组循环
- 2909. 元素和最小的山形三元组 II 1479
- 2483. 商店的最少代价 1495
- 1525. 字符串的好分割数目 1500
- 2874. 有序三元组中的最大值 II 1583
- 1031. 两个非重叠子数组的最大和 1680
- 689. 三个无重叠子数组的最大和
- 2420. 找到所有好下标 1695
- 2100. 适合野炊的日子 1702
- 926. 将字符串翻转到单调递增
- 334. 递增的三元子序列
- 2712. 使所有字符相等的最小成本 1791
- 1653. 使字符串平衡的最少删除次数 1794
- 1186. 删除一次得到子数组最大和 1799
- 1477. 找两个和为目标值且不重叠的子数组 1851
- 2680. 最大或值 1912
- 1671. 得到山形数组的最少删除次数 1913
- 238. 除自身以外数组的乘积 ~2000
- 1888. 使二进制字符串字符交替的最少反转次数 2006
- 2906. 构造乘积矩阵 2075
- 2167. 移除所有载有违禁货物车厢所需的最少时间 2219
- 2484. 统计回文子序列数目 2223
- 2163. 删除元素后和的最小差值 2225
- 2565. 最少得分子序列 2432
- 2552. 统计上升四元组 2433
- 3003. 执行操作后的最大分割数量 3039
- 487. 最大连续 1 的个数 II(会员题)
- 1746. 经过一次操作后的最大子数组和(会员题)
专题:把 X 变成 Y
部分题目也可以用 BFS 解决。
- 397. 整数替换
- 2998. 使 X 和 Y 相等的最少操作次数 1795
- 2059. 转化数字的最小运算数 1850
- 991. 坏了的计算器 1909
- 1553. 吃掉 N 个橘子的最少天数 2048
专题:跳跃游戏
- 1397
- 2770. 达到末尾下标所需的最大跳跃次数 1533
- 403. 青蛙过河
- 1340. 跳跃游戏 V 1866
- 1871. 跳跃游戏 VII 1896
- 1696. 跳跃游戏 VI 1954
- 975. 奇偶跳 2079
- 1654. 到家的最少跳跃次数 2124
- LCP 09. 最小跳跃次数
- LCP 20. 快速公交
- 656. 金币路径(会员题)
- (会员题)
其他 DP
- 1526. 形成目标数组的子数组最少增加次数 1872
- 823. 带因子的二叉树 1900
- 940. 不同的子序列 II 1985
- 135. 分发糖果
- 650. 两个键的键盘
- 467. 环绕字符串中唯一的子字符串
- 2262. 字符串的总引力 2033
- 828. 统计子串中的唯一字符 2034
- 2746. 字符串连接删减字母 2126
- 2930. 重新排列后包含指定子字符串的字符串数目 2227
- 3041. 修改数组后最大化数组中的连续元素数目 2231
- 1569. 将子数组重新排序得到同一个二叉搜索树的方案数 2288
- 818. 赛车 2392
- 920. 播放列表的数量 2400
- 1388. 3n 块披萨 2410
- 1987. 不同的好子序列数目 2422(同 940 题)
- 903. DI 序列的有效排列 2433
- 2272. 最大波动的子字符串 2516
- 1896. 反转表达式值的最少操作次数 2532
- 1531. 压缩字符串 II 2576
- 964. 表示数字的最少运算符 2594
- 1787. 使所有区间的异或结果为零 2640
- 2060. 同源字符串检测 2804
- 2809. 使数组和小于等于 x 的最少时间 2979 排序不等式
- LCP 14. 切分数组
- LCP 36. 最多牌组数
- LCP 38. 守卫城堡
- LCP 43. 十字路口的交通
- LCP 65. 舒适的湿度
- 2189. 建造纸牌屋的方法数(会员题)
- 2597. 美丽子集的数目 *用 DP 解决
- 2638. 统计 K-Free 子集的总数(会员题)上面这题的加强版