斜率优化dp是一种通过构造斜率表达式,用维护凸包的方法来去除多余的点以减少算法复杂度的方法。通常可以将问题规模减小一个维度,从而提高运行效率。
这个算法的关键是将dp的状态转移方程进行转换,比如对于如下状态转移方程:
$$dp[i]=Min(dp[j]+M+(sum[i]-sum[j])^2),j\in [1,i),i\in [1,n]$$
如果直接dp那么复杂度将会是(O(n_2)),某些情况下就会显得效率不够。这时候就可以用斜率dp进行优化,将其优化到$O(n)$。
首先我们需要将状态转移方程进行变形,在计算$dp[i]$的时候,对于任何x和y,如果x比y更优,那么也就是说:
$$\begin{aligned} & dp[x]+M+(sum[i]-sum[x])^2\ \lt dp[y]+M+(sum[i]-sum[y])^2\end{aligned}$$
成立。
将上式进行变形,可以得到一种类似斜率的表达形式:
$$(dp[x]+num[x]^2-(dp[y]+num[y]^2))/(2*(num[x]-num[y]))<sum[i]$$
令:
$$Cmp(x,y)=(dp[x]+num[x]^2-(dp[y]+num[y]^2))/(2*(num[x]-num[y]))$$
现在从左到右,设$x\lt y\lt z$,如果$Cmp(z,y)\lt Cmp(y,x)$,那么y点便永远不可能成为最优解,可以直接将它踢出我们的最优解集。同时,由于$sum[i]$单调增,所以如果$Cmp(y,x)\lt sum[i]$那么x点也不可能成为最优解。
据此,我们可以便可以通过维护这样的一个队列,每加入一个元素就判断排除所有不可能是最优解的点从而进行优化。
斜率优化dp的套路基本是固定的,基本上就是用数组模拟队列,然后两个while循环判断是否可以去除无用的点。
1 |
|
1 |
|
1 |
|
1 |
|