zoukankan      html  css  js  c++  java
  • dp

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

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

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

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

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

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

    示例

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

    转移方程为 (f_i=min(f_j+(s_i-s_j+i-j-L-1)^2)),非常 simple

    我们令和 (i) 有关的为 (a_i=s_i+i),和 (j) 有关的为 (b_j=s_j+j+L+1)

    (f_i=min(f_j+(a_i-b_j)^2))

    拆开 (f_i=min(f_j+a_i^2-2a_ib_j+b_j^2))

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

    (f_i=f_j+a_i^2-2a_ib_j+b_j^2)

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

    主体思想

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

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

    变成 (2a_ib_j+f_i-a_i^2=b_j^2+f_j)。其中 (x=b_j)(y=b_j^2+f_j)

    (P_j) 作为第 (j) 个决策点,坐标为 ((b_j,b_j^2+f_j))

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

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

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

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

    代码

  • 相关阅读:
    C语言考点例题解析
    五笔打字
    常用快捷键
    网络基础知识
    人口增长
    8 封装
    9 绑定方法和非绑定方法
    6 抽象类
    7 多态和多态性
    5 组合
  • 原文地址:https://www.cnblogs.com/LightningUZ/p/13818271.html
Copyright © 2011-2022 走看看