dp深入与进阶(2):特殊的dp优化:斜率优化(无例题解析版)

斜率优化

\(01.\)应用范围:\(f_i=min/max(a_i \times b_j+c_i+d_j)\)这类递推方程式的时间优化

\(02.\)前置推导:

对于\(f_i=min_j(a_i \times b_j+c_i+d_j)\)

其中满足\(b\)单调递增

假设一值\(j_1\)\(dp\)中的作用优于\(j_2\)

则有:

\(a_i \times b_{j_2}+d_{j_2}≥a_i\times b_{j_1}+d_{j_1}\)

可得到:

\(a_i≤\frac{(-d_{j_1})-(-d_{j_2})}{b_{j_1}-b_{j_2}}\)

在平面直角坐标系中 令\(x_j={b_j}\)\(y_j=-d_j\)

\(k(j_1,j_2)=\frac{(-d_{j_1})-(-d_{j_2})}{b_{j_1}-b_{j_2}}\)

显然可知\(a_i≤k(j_1,j_2)\)时,始终满足\(j_1\)的函数值优于\(j_2\)

从而得到结论:

对于坐标系中横坐标单调递增的\(j_1\)\(j_2\)

\(a_i≤k(j_1,j_2)\)\(,f(j_1)\) 优于 \(f(j_2)\)

反之,有\(f(j_2)\) 优于 \(f(j_1)\)

\(03.\)定理雏形证明:

重要定理:对于三个点 A, B, C,假设横坐标递增,且\(k(A,B)>k(B,C)\),可以证明:\(B\)的函数值一定不最优

证明:(不考虑\(a=k\))

为了方便叙述,令\(k_1=k(A,B),k_2=k(B,C)\)

初始图:

1.假设\(a<k_2<k_1:\)

如图,有\(f(A)>f(B)>f(C)\)

2.假设\(k_2<a<k_1:\)

如图有\(f(A)>f(B)\)\(f(C)>f(B)\)

3.假设\(k_2<k_1<a:\)

如图有\(f(C)>f(B)>f(A)\)

可以发现:无论何种情况,\(B\)点一直不是最优的点,所以\(dp\)过程中可以不考虑\(B\)

由此得证

从几何意义上看:如果在建好的的坐标系中发现“上凸包”(“凸包”如上图所示),则凸包的顶点一定不是最优点

\(04.\) 斜率优化的定义:

\(dp\)中忽略所有“上凸包”,优化时间复杂度的优化办法,这样的优化方法即为斜率优化

显然,一个没有上凸包的图\(k\)值一定是单调递减的

所以优化时可以维护一个单调递减的队列来实现

05.一种可行的代码写法

// 计算两点之间的斜率
int slope(int j, int k) 
{
    int x = (f[j] - f[k] + s[j] * s[j] - s[k] * s[k]) / (s[j] + s[k]);
    return x;
}
for (int i = 1; i <= n; i++) 
{
  while (L < R && slope(q[L], q[L + 1]) <= s[i]) L++; // 维护下凸包
    dp[i] = dp[q[L]] + (s[i] - s[q[L]]) * (s[i] - s[q[L]]) + m; // 更新dp值
  while (L < R && slope(q[R - 1], q[R]) > slope(q[R], i)) R--; // 剔除无效点
    q[++R] = i; // 将当前点加入队列
}

最后扔两道例题在这里,下一篇文章或下下篇文章会进行进一步解析

\(1:P3195\)

\(2:P2900\)

posted @ 2025-01-26 16:01  SamXia  阅读(53)  评论(0)    收藏  举报