动态规划技巧
一些对于动态规划的技巧,与优化进行区分。
技巧学过之后是简单的,但是不学基本上写不出来,这些技巧一般只是解题的一小步,或者状态的设计与优化,但其实是至关重要的。
1. 费用提前计算
当 DP 中当前决策会影响未来的费用/贡献,且该费用/贡献仅与当前决策相关,这样我们可以提前计算所影响的费用。
栗子:我们有一些机器,存在一个值表示该机器的价值,选出某个机器可以增加其他所有机器的价值
,则对于选该机器的决策,我们就有固定增加 的贡献,可以提前计算。
什么叫仅呢?再举一个例子,若选择
两个机器会造成额外 的贡献,则对于该式子就不仅与 相关,因为 与两项皆有关。
首先按照
考虑费用提前计算,假设我们选了
所以我们可以得到转移方程:
其中
复杂度
例题
II P4870 [BalticOI 2009 Day1] 甲虫
双倍经验,该题不用喝完所有露水,我们需要枚举所选个数,复杂度
III UVA1336 Fixing the Great Wall
三倍经验。
好题。
首先对于
设
- 若上个操作为
,则因为后面跟着 个 ,相当于 ,即 - 若上个操作位
。- 若
,我们可以相当于加 后,有 个 ,即 。 - 若
,则其末尾 就固定了,而前面我们不关注,所以我们可以直接统计答案,即 。
- 若
最后当结束
我们最多有
可是这与费用提前计算有什么关系呢?我们发现
一个技巧。
首先可以排序,这样对于我们选择的一组学生,其最大值即为最右边的值,则对于每个人有三种情况,最小值/最大值/中间值,所以我们设计
- 若第
个人为新的一组最小值,则 。 - 若第
个人为中间值,则 。 - 若第
个人为某一组最大值,则 。 - 若第
个人单独一组,则 。
这里我们将
可以发现
设
- 若第
个人为新的一组最小值,则 。 - 若第
个人为中间值,则 。 - 若第
个人为某一组最大值,则 。 - 若第
个人单独一组,则 。
这样复杂度是
II 的加强,唯一的区别是本题的蜡烛长度会不同,这样会导致我们选择的熄灭的蜡烛会不是一段连续的区间,我们就不可以枚举区间,考虑到我们费用提前计算的是未熄灭的蜡烛,即这些蜡烛都会变短,这样我们在其基础上加一维
转移类似,多了两种不熄灭该蜡烛的情况需要讨论,复杂度
VII P7650 [BalticOI 2007 Day 1] Ranklist Sorting
神题。
分数各不相同,先离散化好处理,这里将其从大到小排序(意思是最大值为
所以最后我们会得到
首先观察题目,可以感性发现一些性质。
- 若要使某个人
移动,最多让其移动 次,即移动到 前面,移动多次一定不如只移动一次优。 - 对于某个人
,若其向后移动,会使一些人的下标减少,可以减少费用。
可以得出一个 结论:我们的操作应该是从编号大的到编号小的进行操作,且每个人最多操作一次。
对于某个人
分为两种情况。
-
若其要向右移动,设其要到达的位置为
:因为每次所造成的贡献是当前下标,所以我们需要考虑求出,因为我们从大到小操作,根据结论可知,所有小于
的数都没有动,即 所在原位置前面小于 的数是可知的,而所有大于 的数一定在右边,因为 ,所以 所在的真实位置是下标小于 且大小小于 的数目 ,设 表示前 个数中 的数目,则当前 所在真实位置即为 ,同理我们可以得出 的真实位置为 。-
则若移动至
前面的贡献为 。所以有
。 -
因为
,所以其实我们可以不移动,让在 中间的数向前移动,但是该决策会影响向左移动的人的费用,我们考虑费用提前计算,对于 ,我们计算 只计算了下标小于 ,大小小于 ,的值,所以若 , 还需要跳过 个数,因为我们已经假设所有 的数已经聚到一起,即所有 的数都在 之前。所以有
。
-
-
若其要向左移动,设其要到达的位置为
。去除掉不移动的人的影响,这种情况必须移动,所以贡献为
。
总转移有:
。 。
答案即为
这里为了方便,添加了一个
复杂度
2. 假设未来决策
3. 状态设计
状态设计是 DP 的核心。
例题
首先有显然的
对于固定
我们将枚举
即得
复杂度
参考文章
对一类动态规划问题的研究 - 徐源盛 2009
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具