5.0 KiB
# 【学习笔记】动态规划—各种 DP
优化
【大前言】
个人认为贪心,dp
是最难的,每次遇到题完全不知道该怎么办,看了题解后又瞬间恍然大悟(TAT)。这篇文章也是花了我差不多一个月时间才全部完成。
【进入正题】
用动态规划解决问题具有 空间耗费大、 时间效率高 的特点,但也会有时间效率不能满足要求的时候,如果算法有可以优化的余地,就可以考虑时间效率的优化。
【DP
时间复杂度的分析】
DP
高时间效率的关键在于它减少了 冗余 ,即不必要的计算或重复计算部分,算法的冗余程度是决定算法效率的关键。而动态规划就是在将问题规模不断缩小的同时,记录已经求解过的子问题的解,充分利用求解结果,避免了反复求解同一子问题的现象,从而减少 冗余
但是,一个动态规划问题很难做到完全消除 冗余
下面给出动态规划时间复杂度的决定因素:
时间复杂度 = 状态总数 × 每个状态转移的状态数 × 每次状态转移的时间
【DP
优化思路】
一:减少状态总数
(1). 改进状态表示
(2). 选择适当的规划方向
二:减少每个状态转移的状态数
(1). 四边形不等式和决策的单调性
(2). 决策量的优化
(3). 合理组织状态
(4). 细化状态转移
三:减少状态转移的时间
(1). 减少决策时间
(2). 减少计算递推式的时间
(上述内容摘自 《动态规划算法的优化技巧》毛子青 ,想要深入了解其思想的可以去看看这篇写得 超级好 的论文。)
看到这里是不是已经感觉有点蒙了呢? 本蒟蒻总结了一个简化版本:
【DP
三要点】
在推导 dp
方程时,我们时常会感到毫无头绪,而实际上 dp
方程也是有迹可循的,总的来说,需要关注两个要点:状态,决策和转移。其中 状态最为关键, 决策最为复杂。
【状态】
关于 状态 的优化可以从很多角度出发,思维难度极其高,有时候状态选择的好坏会直接导致出现 爆零 和 满分 的分化。
【决策】
与 状态 不同,决策 优化则有着大量模板化的东西,在各大书籍,文章上你都可以看到这样的话:只要是形如 XXX
的状态转移方程,都可以用 XXX
进行优化。
【转移】
转移 则指由最优决策点得到答案的转移过程,其复杂度一般较低,通常可以忽略,但有时也需要特别注意并作优化。
本文将会重点针对 决策 优化部分作一些总结,记录自己的感悟和理解。
QAQ
一:【矩阵优化 DP
】
updata
之后由于篇幅过大,已搬出。。。。。
TODO 挖坑待填
补充:其实质是优化 转移。
QAQ
二:【数据结构优化 DP
】
【前言】
在一些 dp
方程的状态转移过程中,我们通常需要在某个范围内进行择优,选出最佳决策点,这往往可以作为 dp
优化的突破口。
数据结构的使用较灵活,没有一个特定的模板,需要根据具体情况而定,选择合适的方案。由于状态转移总是伴随着 区间查询最值,区间求和 等操作,即 动态区间操作,所以 平衡树 可以作为一个有用的工具,但考虑到代码复杂度,使用 树状数组 或者 线段树 将会是一个不错的选择。
其实质是优化 决策。
1.【维护合适的信息】
以 The
Battle
of
Chibi
[UVA12983
] 为例,大概题意就是计算在给定的序列中严格单调递增子序列的数量,并对 1e9+7
取模,给定序列长度小于等于 1000
。
方程应该是比较好推的,用 dp[i][j]
表示由序列中在 j
之前的数构成并以 a[j]
结尾的子序列中,长度为 i
的子序列的数量。则:
\large dp[i][j]=\sum dp[i−1][k]
Q:
状态用一维表示行不行?A
:如果是一维表示,那么就是表示由序列中在j
之前的数构成并以a[j]
结尾的子序列的数量。这时考虑一下状态转移,看看它的前序状态是怎么样转移过来的:枚举它前面所有的数字,a[k]<a[j]
,这样不行吗? 不行,比如1~ 2~ 2~ 2~ 6 ~ 3~ 3~ 4
,因为存在重复数字2
,会造成统计重复,无法去重。 办法就是增加一个维度,还要记录以k
结尾时的子序列长度,就解决了去重的问题。
对于决策点 dp[i−1][k]
这里出现了 3
个信息:
- 在原序列中的位置
k<j
。 a[k]<a[j]
。dp[i−1][k]
的和。