前言:
也是好久没有写题解了,最近主要学习了单调栈单调队列以及斜率优化DP这几个知识点,对于较难的斜率优化DP,做个小小的总结吧。
正(che)文(dan):
T1 hdu 3507
在一个风和日丽的早上,你打开了网页,点进了hdu,偶然间看到了这道题,不屑的以为这仅仅是一个很水的DP,2分钟给出DP方程式,很快的写完后发现n的范围居然是500000,这让已经推出来的 O(n2)复杂度的递推式情何以堪,所以就产生了一种高逼格的优化方式:斜率优化。
这道题的方程式是什么呢?
dp[i]=min(dp[j]+sum[i]2?sum[j]2+M),j∈(0,i)
我们发现从1到n计算i的时候,每一次都是将1~i?1的最优决策拿出来更新i,所以我们可不可以搞出来一种方式来维护这个最优解,使得在i递增的时候每次更新都能在O(1)的时间拿出来这个解呢。
我们先假设两个决策k和j,且j>k。
对于二者来说他们对应的值分别为:
dp[j]+(sum[i]?sum[j])2+M
dp[k]+(sum[i]?sum[k])2+M
如果这个时候j这个决策是比k优的,那么说明j是完全可以取代k的,因为j是在k的后面出现,随着时间的递增,可以证明k是不可能再比j优的,所以这个时候可以删掉j,但是反之就是不一定的,因为随着时间的递增j有可能更优于k,所以不可以删掉k>
j优于k时
dp[j]+(sum[i]?sum[j])2+M<=dp[k]+(sum[i]?sum[k])2+M
则
dp[j]?dp[k]+sum[j]2?sum[k]22?(sum[j]?sum[k])<=sum[i]
我们把
dp[j]?dp[k]+sum[j]2?sum[k]22?(sum[j]?sum[k])
叫做g[k,j]
那么就可以得到这个结论
对于决策k与j来说,k<j,如果g[k,j]<sum[i],那么就是在i这个时间点时,j优于k。
所以到i时,在给dp[i]赋值之前,需要维护这个队列的队首,如果g[q[head],q[head+1]]<=sum[i]
q[head+1]已经比q[head]更优了,所以head就可以删掉,这样我们每次从队头拿出来的值都是最优的值
然而队尾的处理就没有那么简单了,因为两个决策的时候不好考虑删不删,所以我们引入第三个决策l且k<j<l
如果g[k,j]>g[j,l]
- g[j,l]>sum[i]
则说明j比l优,此时我们并不能做什么,但是同时g[k,j]>g[j,l]>sum[i]
所以又有k比j优,这个时候符合已经推导出来的删点法则,我们就可以把j这个决策删除了
- g[j,l]<=sum[i]
则说明l比j优,根据删点法则,直接可以把j给删除,
那么从另一个角度说,g[k,j]>g[j,l]的时候是删除掉j的。
所以我们维护的是g[k,j]<=g[j,l]的情况也就是一个下凸函数(传不上图…)
这样分别去维护队首以及队尾就可以搞定这道题。
T2 玩具装箱
维护的仍然是最小值。
这道题也是挺简单的,只是在推导过程中心细一点就可以了。
我在这道题上将sum[i]定义为1~i的求和以及间隔数,以便推导时更加简洁。
最后推导出来的斜率式子是:
dp[j]?dp[k]+(sum[j]?sum[k])?(sum[j]+sum[k]+2?(L+1))2?(sum[j]?sum[k])
其他的重复上一题的过程。
T3 特别行动队
这道题要求的是维护最大值,与之前两道题并不同,但本质上也没差多少。
最后推导出来的斜率式子是:
dp[j]?dp[k]+a?(sum[j]?sum[j]?sum[k]?sum[k])+b?(sum[k]?sum[j])2?a?(sum[j]?sum[k])
其他的重复上一题的过程。
T4 USACO 2008 Mar Gold 1.Land Acquisition
这道题与之前的有些不同的是,需要加上一点贪心的思想,也就是说我们按照宽度或者长度从大到小排序,如果相等的话,另一个因素按照从大到小排序,这样再重新扫一遍所有的土地,以便除掉被其他土地包含的土地。再进行DP就可以了。
最后推导出来的斜率式子是:
b[k+1].w?b[j+1].wdp[j]?dp[k]
其他的重复上一题的过程。
待续······