闫式DP分析法
学好DP的一个关键点在于刷遍所有类型的DP题目
- 选择DP问题:背包模型
- 序列DP问题
- 状态压缩问题
- 状态机问题
- 树形DP问题
- 区间DP问题
- 斜率优化问题
1. 核心思想——集合
闫式DP分析法的核心思想是从集合的角度来分析DP问题。
所有的DP问题都可以使用闫式DP分析法进行分析。(经过70道题目验证通过????)
我们可以把做过的所有DP问题都看作是有限集上的最值问题。
DP问题 == 有限集上的最值问题
然而,由于这个有限集的数量级很高(通常是指数级别的),所以肯定不能暴力地进行枚举,时间复杂度会过高。则需要使用DP来进行优化,DP的两个阶段:
-
化零为整,寻找共性——状态表示
所谓 化零为整 是指我们对于零星的情况,不是一个一个去枚举,而是每次根据这些零星的情况的某些特性去枚举一类情况(即一个子集)
f(i)需要考虑的问题:- 表示的是一个怎样的集合?
f(i)
保存的值是什么意思(max/min/count/…)?与集合有什么关系?
-
化整为零,寻找不同——状态计算
如何去求
f(i)
呢?
我们要把它们划分成若干个不同的子集来求,每一个子集分别去求。需要满足的条件有:- 不重复(可以不满足,例如求
min
,max
。但是求count的时候,就不能重复) - 不遗漏
例如,我们假设f(i)表示的是某个集合的最大值,那么可以每个子集的最大值的最大值。
- 不重复(可以不满足,例如求
那么问题来了,怎么进行集合f(i)
的划分呢?
寻找最后一个不同点。
2. 01背包问题
2.1 集合
集合的描述一般是有套路的:所有满足条件1,条件2的元素的集合。
这个条件1和条件2一般对应到我们的状态表示的每一维。
2.2 属性
一般是根据题目是要求什么来确定的。
2.3 状态计算
集合f(i)
的划分就是寻找最后一个不同点。对于01背包问题,最后一个不同点就是,选第i
个物品和不选第i
个物品是两种不同的方案。
注意:
- DP的优化是在DP的朴素分析完成之后才进行的。所以得先想好朴素分析,不要急于求成;
- DP问题的所有优化都是对代码做等价变形;