形式
形如
dp[i]=max(dp[j]−a[i]×b[j]+c[j])+d[i]dp[i]=max(dp[j]−a[i]×b[j]+c[j])+d[i]
的dp方程 (a[x],b[x],c[x],d[x]a[x],b[x],c[x],d[x]为一些与x有关的式子)
(需保证b[x]满足单调性)
如果是min,则后面的过程反过来,自己理解去。
思路
为了O(1)O(1)选出最优的j,假设dp[j]dp[j]优于dp[k]dp[k],且b[j]>b[k]b[j]>b[k]
即,
dp[j]−a[i]×b[j]+c[j]>dp[k]−a[i]×b[k]+c[k]dp[j]−a[i]×b[j]+c[j]>dp[k]−a[i]×b[k]+c[k]
变成
(dp[j]+c[j])−(dp[k]+c[k])b[j]−b[k]>a[i](dp[j]+c[j])−(dp[k]+c[k])b[j]−b[k]>a[i]
所以要求(dp[j]+c[j])−(dp[k]+c[k])b[j]−b[k](dp[j]+c[j])−(dp[k]+c[k])b[j]−b[k] 斜率越大越好,用单调队列维护
把上面那个b[j]b[j]当做横坐标,(dp[j]+c[j])(dp[j]+c[j])当做纵坐标。
维护的单调队列要使斜率要递减(保证前面的更大),画成图像就成了一个上凸包:
实现
对于一个新的ii,保证最大,队列的左边为headhead,判断head与head+1的斜率,如果head+1更优,即
(dp[head+1]+c[head+1])−(dp[head]+c[head])b[head+1]−b[head]>a[i](dp[head+1]+c[head+1])−(dp[head]+c[head])b[head+1]−b[head]>a[i]
那么就
head++; 所以dp[i]dp[i]就从head位置转移过来。
接下来把dp[i]dp[i]添加进单调队列,把队尾tail斜率比i小的全部弹出去,即
(dp[i]+c[i])−(dp[tail]+c[tail])b[i]−b[tail]>(dp[tail]+c[tail])−(dp[tail−1]+c[tail−1])b[tail]−b[tail−1](dp[i]+c[i])−(dp[tail]+c[tail])b[i]−b[tail]>(dp[tail]+c[tail])−(dp[tail−1]+c[tail−1])b[tail]−b[tail−1]
那么就
tail--; 最后把i放进tail里。

本文介绍了一种针对特定形式动态规划方程的优化方法,通过维护斜率递减的单调队列来达到O(1)选取最优状态的目的。
1728

被折叠的 条评论
为什么被折叠?



