dp - 斜率优化笔记

(原来的题解没得了,只好重写一份)

斜率优化一般是,dp 是枚举一个 i,然后前面找一个 j,式子中有些和 j 有关,有些和 i 有关,有些和俩都有关。

过程中,我们维护一个单调队列,它们可能作为最优的转移位置。其中队首是最优的,其它的是 可能 成为最优的(现在不是,可能以后)

核心步骤:把每个决策转化成平面直角坐标系上的点,然后从几何的角度考虑哪些点可能是最优的,哪些不可能。

我们发现这个性质好像很妙。所以说,不是所有题都可以斜率优化的。

这些说的肯定非常迷惑,看个实际的

示例

最经典的入门题 HNOI2008玩具装箱

转移方程为 fi=min(fj+(sisj+ijL1)2),非常 simple

我们令和 i 有关的为 ai=si+i,和 j 有关的为 bj=sj+j+L+1

fi=min(fj+(aibj)2)

拆开 fi=min(fj+ai22aibj+bj2)

假设 j 是最优的那个转移,那

fi=fj+ai22aibj+bj2

这个式子里面,注意到 2aibj 这一项是同时与俩有关的。

主体思想

我们把和 i 有关的那个 2ai 看成斜率,和 j 有关的 bj 看成 x。那 y 肯定也要和 j 有关,移到右边。我们的主体思想是把 fi 变成一个截距。所以把 fi 和一些只和 i 有关的东西放到左边。

(这一步就体现出“斜率”了)

变成 2aibj+fiai2=bj2+fj。其中 x=bjy=bj2+fj

Pj 作为第 j 个决策点,坐标为 (bj,bj2+fj)

那现在问题转化成了:找到一个 j<i,使得过点 Pj 的斜率为 2ai(定值)的直线的截距加上 ai2(定值)最小。

手画几张图可以得出以下结论:

  • 如果队首的斜率 <2ai,那这一次转移队首就比队首的下一个要劣(画图发现);而且 ai 是单增的,那以后肯定都劣,直接弹队首
  • 斜率应该是单调递增的 (这个要手画了)。所以如果新来的和原队尾组成的斜率,小于原队尾和原队尾上一个的斜率,那这个队尾就废了

然后就维护一个单调队列就完事了。复杂度是 O(n) 的,log 都不带。

代码

posted @   Flandre-Zhu  阅读(96)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示