EagleBear2002 的博客

这里必须根绝一切犹豫,这里任何怯懦都无济于事

P3195 [HNOI2008] 玩具装箱

题目链接:P3195 [HNOI2008] 玩具装箱 - 洛谷

本题是经典 DP 斜率优化题型。

题目描述

P 教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。

P 教授有编号为 1nn 件玩具,第 i 件玩具经过压缩后的一维长度为 Ci

为了方便整理,P 教授要求:

  • 在一个一维容器中的玩具编号是连续的。
  • 同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物。形式地说,如果将第 i 件玩具到第 j 个玩具放到一个容器中,那么容器的长度将为 x=ji+k=ijCk

制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为 x,其制作费用为 (xL)2。其中 L 是一个常量。P 教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过 L。但他希望所有容器的总费用最小。

输入格式

第一行有两个整数,用一个空格隔开,分别代表 nL

2 到 第 (n+1) 行,每行一个整数,第 (i+1) 行的整数代表第 i 件玩具的长度 Ci

输出格式

输出一行一个整数,代表所有容器的总费用最小是多少。

输入输出样例 #1

输入 #1

1
2
3
4
5
6
5 4
3
4
2
1
4

输出 #1

1
1

说明/提示

对于全部的测试点,1n5×1041L1071Ci107

题解

参考文档:斜率优化 - OI Wiki

状态定义和转移

定义 f(i) 为前 i 个物品收纳的最小费用。

边界条件:

f(0)=0

状态转移方程:

f(i)=min0j<i{f(j)+p(j+1,i)}

其中,p(l,r) 表示将区间 [l,r] 装到同一个容器的代价。

p(l,r)=(rl+k=lrCkL)2=(rl+srsl1L)2

其中,si 表示 Ci 的前缀和。

最终答案即为 f(1,n)

该解法的时间复杂度为 Θ(n2),无法通过本题。

DP 斜率优化

状态转移方程可转化为:

f(i)=min0j<i{f(j)+(i(j+1)+sisjL)2}=min0j<i{f(j)+(si+i(sj+j)(L+1))2}=min0j<i{f(j)+(titj(L+1))2}=min0j<i{f(j)+ti2+tj2+(L+1)22titj2ti(L+1)+2tj(L+1)}

其中,ti=si+i

将与 j 无关的项移到等式左边:

f(i)ti2+2ti(L+1)(L+1)2=min0j<i{f(j)+tj2+2tj(L+1ti)}

使用线性规划的思路来处理方程:考虑一次函数的斜截式 y=kx+b,将其移项得到 b=ykx。我们将与 j 有关的信息表示为 y 的形式,把同时与 i,j 有关的信息表示为 kx,把要最小化的信息(与 f(i) 有关的信息)表示为 b,也就是截距。具体地,令

xj=tjyj=f(j)+tj2ki=2(L+1ti)bi=f(i)ti2+2ti(L+1)(L+1)2

则转移方程就写作 bi=minj<i{yjkixj}。我们把 (xj,yj) 看作二维平面上的点,则 ki 表示直线斜率,bi 表示一条过 (xj,yj) 的斜率为 ki 的直线的截距。问题转化为:选择合适的 j1j<i),最小化直线的截距。

如图,我们将这个斜率为 ki 的直线从下往上平移,直到有一个点 (xp,yp) 在这条直线上,则有 bi=ypkixp,这时 bi 取到最小值。算完 f(i) 后,我们就把 (xi,yi) 这个点加入点集中,以做为新的 DP 决策。那么,我们该如何维护点集?

容易发现,可能让 bi 取到最小值的点一定在下凸壳上。因此在寻找 p 的时候我们不需要枚举所有 i1 个点,只需要考虑凸包上的点。而在本题中 kii 的增加而递增,因此我们可以单调队列维护凸包。

具体地,设 K(a,b) 表示过 (xa,ya)(xb,yb) 的直线的斜率。考虑队列 ql,ql+1,,qr,维护的是下凸壳上的点。显然下凸壳上的斜率 K(a,b) 是单增的,即,对于 l<i<r,始终有 K(qi1,qi)<K(qi,qi+1) 成立。

我们维护一个指针 e 来计算 bi 最小值。我们需要找到一个 K(qe1,qe)ki<K(qe,qe+1)e(特别地,当 e=l 或者 e=r 时要特别判断),这时就有 p=qe,即 qei 的最优决策点。由于 ki 是单调递增的,因此 e 的移动次数是均摊 O(1) 的。

在插入一个点 (xi,yi) 时,我们要判断是否 K(qr1,qr)<K(qr,i),如果不等式不成立就将 qr 弹出,直到等式满足。然后将 i 插入到 q 队尾。

这样我们就将 DP 的复杂度优化到了 Θ(n)