决策单调性优化 DP
前言
本文将介绍决策单调性优化 DP 的相关内容。持续更新修正,如有差错请指出。
1.四边形不等式优化 DP
1.1 四边形不等式与决策单调性
- 四边形不等式:如果对于任意的 均成立
则称代价函数 满足四边形不等式。观察上述形式,即包含劣于相交,注意这是当我们要求代价函数 最小时四边形不等式的符号,如果我们要求 最大,相当于对其取相反数,那么相应的,此时的四边形不等式需要变号。
四边形不等式优化利用的是状态转移方程中的决策单调性,通常用于解决一系列的最优化问题。
在解决动态规划相关问题的时候,通常会遇到以下这种形式
其中 也可能是 。一般情形下,这类问题解决的时间复杂度为 ,如果 具有决策单调性,那么就可以将时间复杂度优化至 甚至 。
- 决策单调性:设 表示 取到最小值时 的值(如果有多个 满足则取最小),即 的最优决策点。当代价函数 满足四边形不等式时, 在 上单调不降, 具有决策单调性。则我们有
要证明这一点,可以使用反证法。假设对于 ,其最优决策点 ,此时 ,据四边形不等式有 但是根据决策点的最优化条件又有 ,即 与四边形不等式矛盾。
由此得证。
对于 ,其具有最小/最大最优决策点,将上述对 的定义更换为取最大后,关于原 的所有结论都是同样成立的,最大最优决策点同样具有单调不降的性质。注意可能存在 ,但是 的最大最优决策点小于 的最小最优决策点,故一般题目当中我们都默认只取最小(大)最优决策点来转移。
1.2 解题套路
通常我们先写出 的转移式子,大多数情况下,通常使用
来检验代价函数是否满足四边形不等式。
然后对于一个决策,取它作为最优决策点的 所组成的是一个区间。对于决策 ,则这两种决策能成为最优决策的区间 ,有 。
我们写一个二分函数 计算出第一个以 作为最优决策不如以 作为最优决策优秀的点,那么可以使用单调队列来维护最优决策点,并进行 DP 转移了。
2.斜率优化 DP
给出例题。
- P3195 玩具装箱
对于 ,其代价为 。
首先对 做前缀和。考虑暴力,对于每个 去枚举 ,则有
rep(i,1,n) {
dp[i] = inff;
rep1(j,i - 1,0)
chmin(dp[i],dp[j] + (i - j - 1 + c[i] - c[j] - L) * (i - j - 1 + c[i] - c[j] - L));
}
现在进行优化,把上述式子变形,把 放入 中, 分别放入 中,有 ,把式子里的“常量”提出来展开,变为
接下来考虑进行斜率优化,对于一个一次函数 ,通常推式子时有以下操作:
- 把要求最小值的式子作为截距,即
- 把另一边的式子变为 的形式,其中 只与 有关, 同时与 有关
显然, 取到最小值的点在这个下凸壳上,因为这个斜率是单调的,可以考虑用单调队列来维护,此时 。
那么当 , 在 上取得最小值。
代码就很好写了。
il db slope(int i,int j) {
return (db)(y[i] - y[j]) * 1.0 / (db)(x[i] - x[j]);
}
il void solve() {
//------------code------------
read(n,L);
++ L;
rep(i,1,n) read(c[i]),c[i] += c[i - 1];
rep(i,1,n) c[i] += i;
rep(i,1,n) {
int k = 2ll * (c[i] - L);
while (hh <= tt && slope(q[hh - 1],q[hh]) <= k * 1.0) ++ hh;
dp[i] = y[q[hh - 1]] - k * x[q[hh - 1]] + (c[i] - L) * (c[i] - L);
x[i] = c[i],y[i] = dp[i] + c[i] * c[i];
while (hh <= tt && slope(q[tt - 1],q[tt]) >= slope(q[tt],i)) -- tt;
q[++ tt] = i;
}
write(dp[n],'\n');
return ;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律