DP 优化

今天模拟赛考到了斜率优化,我发现去年暑假听得一知半解的知识点现在要彻底搞懂了。

本文我学到哪写到哪。

决策单调性优化

有些状态 \(a\)\(b\) 总是要好(譬如花费更低而收益更高),那么 \(b\) 状态可以丢掉。

斜率优化

参考资料:https://oi-wiki.org/dp/opt/slope

P3195 [HNOI2008] 玩具装箱

题意

\(n\) 个玩具,第 \(i\) 个玩具价值为 \(c_i\) 。要求将这 \(n\) 个玩具排成一排,分成若干段。对于一段 \([l,r]\) ,它的代价为 \((r-l+\sum_{i=l}^r c_i-L)^2\) 。其中 \(L\) 是一个常量,求分段的最小代价。

\(1\le n\le 5\times 10^4, 1\le L, c_i\le 10^7\)

朴素 DP

\(dp_i\) 表示考虑到第 \(i\) 个物品,分若干段的最小代价。

容易推出:

\[dp_i=\min_{j<i}\{dp_j+val_{j+1,i}\} \]

\[val_{l,r}=(r-l+\sum_{i=l}^r c_i-L)^2 \]

前缀和优化

\[dp_i=\min_{j<i}\{dp_j+val_{j+1,i}\} \]

\[val_{l,r}=(r-l+pre_r+pre_{l-1}-L)^2=\Big(r+pre_r-(l-1)-pre_{l-1}-1-L\Big)^2 \]

为了简化式子,构造函数 \(S_i=pre_i+i\),并设 \(L'=L+1\)

\[dp_i=\min_{j<i}\{dp_j+(S_i-S_j-L')^2\} \]

这个样子已经基本可以确定是斜率优化了。但是我们进一步化简:

\[dp_i=\min_{j<i}\{dp_j+S_j^2+2\cdot S_j \cdot (L'-S_i)\}+(S_i-L')^2 \]

斜率优化

我们要把转移方程转化成一次函数斜截式的形式。\(\mathcal{OIwiki}\) 是这样说的:

考虑一次函数的斜截式 \(y=kx+b\) ,将其移项得到 \(b=y-kx\) 。我们将与 \(j\) 有关的信息表示为 \(y\) 的形式,把同时与 \(i,j\) 有关的信息表示为 \(kx\) ,把要最小化的信息(与 \(i\) 有关的信息)表示为 \(b\) ,也就是截距。

\[b=dp_i-(S_i-L')^2 \]

\[y=dp_j+S_j^2 \]

\[-k=2\cdot(L'-S_i) \]

\[x=S_j \]

原方程表示为

\[b_i=\min_{j<i}\{y_j-k_i\cdot x_j\} \]

接下来,我们考虑几何意义。

图片来源于 \(\mathcal{OIwiki}。\)

发现要求截距最小。所以我们要找到合适的 \(j\)

我们每对一个 \(i\) 求出最优转移点 \((x_j,y_j)\),先算出 \(dp_i\),然后将求出的新点 \((x_i,y_i)\) 放入坐标系。

存在性质:

  1. 只有下凸壳的点可能作为转移点。
  2. \(S_i\)\(i\) 单调递增,\(k_i\)\(i\) 单调递增。

由性质得,可以用单调队列维护下凸壳(凸包上的转移点位置存在单调性)。

剩下的不必多说,这里偷懒放下 \(\mathcal{OIwiki}\) 的解释。

将初始状态入队。
每次使用一条和 \(i\) 相关的直线 \(f(i)\) 去切维护的凸包,找到最优决策,更新 \(dp_i\)
加入状态 \(dp_i\) 。如果一个状态(即凸包上的一个点)在 \(dp_i\) 加入后不再是凸包上的点,需要在 \(dp_i\) 加入前将其剔除。

posted @ 2023-08-18 16:57  xcr0987  阅读(36)  评论(0)    收藏  举报