zoukankan      html  css  js  c++  java
  • 动态规划优化之斜率优化(基础)

    原文链接http://www.cnblogs.com/zhouzhendong/p/8697303.html

    前置技能

    • 知道什么是动态规划,并对一般的动态规划较为了解
    • 比较熟悉单调队列,并做过单调队列的题
    • 对斜率以及凸包有一定的了解
    • 有一定的推式子的能力

    斜率优化可能是什么?

      顾名思义,就是通过一系列的推导把式子转化成斜率的形式,然后利用一些性质进行优化。

    问题模型

      有一个长度为$n$的序列$a$,第$i$项元素为$a_i$。保证$a_i$为正整数。

      现在请你把这个序列分成若干段。设某一段是从$j$开始$i$结束的,设这个区间的所有的数字的总和为$x$,那么它的花费就是$V=ax^2+bx+c$(这里的a(a>0),b,c会输入,都是常数,别和序列$a$搞混)。

      一种划分方式的总花费就是他每一段的花费的和。

      问所有划分方式中总花费最小是多少。

      $nleq 5 imes 10^6$。

    解决方法

      首先我们设$dp_i$表示序列前$i$个元素组成的前缀序列的最小总花费。

      设

      $$sum_i=sum_{j=1}^{i}a_j$$

      我们可以列出DP方程:

      $$dp_i=max{dp_j+a(sum_i-sum_j)^2+b(sum_i-sum_j)+c}  (0leq j<i)$$

      我们假设$j>k$且从$j$转移比从$k$不劣,则:

      $$dp_j+a(sum_i-sum_j)^2+b(sum_i-sum_j)+cleq dp_k+a(sum_i-sum_k)^2+b(sum_i-sum_k)+c$$

      $$dp_j+a(sum_i-sum_j)^2+b(sum_i-sum_j)leq dp_k+a(sum_i-sum_k)^2+b(sum_i-sum_k)$$

    $$dp_j+acdot sum_i^2-2acdot sum_isum_j+acdot sum_j^2+bcdot sum_i-bcdot sum_jleq dp_k+acdot sum_i^2-2acdot sum_isum_k+acdot sum_k^2+bcdot sum_i-bcdot sum_k$$

      $$dp_j-2acdot sum_isum_j+acdot sum_j^2-bcdot sum_jleq dp_k-2acdot sum_isum_k+acdot sum_k^2-bcdot sum_k$$

      $$(dp_j+acdot sum_j^2-bcdot sum_j)- (dp_k+acdot sum_k^2-bcdot sum_k)leq 2acdot sum_i(sum_j-sum_k)$$

      由于$sum$递增,而$j>k$,所以$sum_j-sum_k>0$,所以可以将上式继续转化:

      $$frac{(dp_j+acdot sum_j^2-bcdot sum_j)-(dp_k+acdot sum_k^2-bcdot sum_k)}{sum_j-sum_k}leq 2acdot sum_i$$

      我们设

      $$x_p=sum_p$$

      $$y_p=dp_p+acdot sum_p^2-bcdot sum_p$$

      则原不等式可写为:

      $$frac{y_j-y_k}{x_j-x_k}leq 2acdot sum_i$$

      于是你会惊奇的发现,$Largefrac{y_j-y_k}{x_j-x_k}$不就是斜率的式子吗?

      设

      $$g_{i,j}=frac{y_i-y_j}{x_i-x_j}$$

      则上式可以表示为$g_{j,k}leq sum_i$

      我们来发掘以下$g_{j,k}$的性质。

      1. 当$g_{j,k}leq sum_i$时,由于随着$i$变大,$sum_i$也变大,所以显然从$k$转移是永远不会比$j$好的,所以我们可以把$k$扔掉。

      2. 当$g_{i,j}leq g_{j,k}$时,从$i$或者$k$转移至少有一个不比$j$差,所以可以把$j$扔掉。为什么??

        若$g_{i,j}leq sum_i$,显然$j$要被扔掉,根据第一个性质。

        若$g_{i,j}>sum_i$,则$g_{j,k}>sum_i$,那么显然$j$比$k$差,也得被扔掉。

      于是我们可以用一个单调队列来维护斜率的单调性。

      具体的:

      当情况1发生的时候让队首出队。

      在进队的时候,如果发生情况2,那么先让队尾出队,然后再进队。

      为了避免精度问题,我们可以把$x_i-x_j$乘上来。写成乘积的形式来比大小。

      显然每次要选队头的决策最赚。

      那么我们再思考一下,既然叫做斜率优化,那么显然有一些关于斜率的性质。

      我们如果把上述的决策放到单调队列里,然后再平面直角坐标系中描出这些点,并依次相连,会得到一个这样的图:

      

      然后你会发现这个右下角是个凸包的一部分。我们叫他下凸壳。

      然后你就和凸包联系起来了。

      由于博主见识短浅,所以不再进行凸包性质的拓展。

      读者可以自己科普。

      例子就这么快的讲完了,请读者好好回顾,务必理解。

      我直接开始放例题了。

    例题

      以下例题链接是较为详细的题解(点击题号即可进入)。题解上部有题目链接。

    BZOJ1911

    题意

      把一个整数序列划分成任意连续的段,使得划分出来的每一段的价值和最大。对于某一段,价值的计算公式为 $V=ax^2+bx+c$,其中 $x$ 为当前段的数值和。

      $1leq nleq 1000000,-5leq aleq -1,|b|leq 10000000,|c|leq 10000000,1leq xileq 100$

    提示

      注意这题和例题非常相似,但是注意一个很大的不同!这里的$a$为负数。所以很多不等式符号都要取相反方向。

    BZOJ1597

    题意

      有N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000,000; 1 <= 长 <= 1,000,000). 每块土地的价格是它的面积,但可以同时购买多快土地. 这些土地的价格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果FJ买一块3x5的地和一块5x3的地,则他需要付5x5=25. FJ希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费.

    提示

      考虑到如果长方形A的长和款都比B小,那么A就可以附着在B里面买,而且不加花费,所以这些可以删掉,是没用的。

      本题由于是我很久以前做的,题解没有用Latex,所以特别丑,请别介意。

      请注意两块相同土地的情况,别全都删光。

      然后把土地按照长升序排列,得到的土地的宽必然是降序的,所以就可以很快写出DP方程并斜率优化了。

    BZOJ1010

    题意

      划分序列,每一段的花费为$(i-j+(sum_{k=i}^j C_k)-L)^2$,问最小花费。序列长度$leq 5 imes 10^4$。

    提示

      DP方程应该很好写吧。

      手工展开式子得到关于$i$的二次项,关于$j$的二次项,以及$kcdot ij$这种形式。

      根据斜率优化的套路,把只含$i$的左右消掉,把含$i,j$或者$i,k$的移向同一侧,然后除过来。

    BZOJ3156

    题意

      长为$n$的序列$A$划分,设某一段为$[i,j]$,则其花费为$A_j+sum_{k=i}^{j}(j-k)$。最小化总花费。$nleq 10^6$。

    提示

      同样也是化开,再按照斜率优化的套路来。

      为了避免精度问题,我们可以通过把$x,y$同时乘上一个常数来除去分母对精度的影响。

     

    BZOJ3437

    题意

      每一段的花费为$a_i+sum_{k=j+1}^{i}(i-k)b_k$.最小化总花费。$nleq 10^6$。

    提示

      考虑预处理带权前缀和$vsum_i=sum_{j=1}^{i}(jcdot b_j)$。

      

    BZOJ1096

    题意

      每一段的花费为$a_i+sum_{k=j+1}^{i}(X_i-X_k)b_k$.最小化总花费。$nleq 10^6$。

    提示

      上一题的一个小小的升级版。

      考虑把预处理的带权前缀和改为$vsum_i=sum_{j=1}^{i}(X_jb_j)$。

     

    BZOJ3675

    题意

      对于一个非负整数序列,小H需要重复k次以下的步骤:

      1.选择一个长度超过1的序列

      2.从任意位置将序列分割成两个非空的新序列。

      每次,小H将会得到分数。分数为两个新序列中元素和的乘积。请选择一种最佳的分割方式,使得k轮之后,使总得分最大。输出总得分。

      $nleq 10^5,kleq min(n-1,200)$

    提示

      这题比较不错。

      首先证明一个性质:对于一个最终的划分方案,以各种不同顺序划分,所得到的得分总是相同。

      然后$dp_{r,i}$表示划分到前$i$个,划分了$r$轮的最大总得分。然后斜率优化。

      注意空间限制较紧,要滚动。

    BZOJ4409

    题意

      有一个N个点的环,相邻两个点距离是1。点顺时针标号为1..N。最初每一个点是空的。要求最终点i存在ri头牛。你有∑ri头牛。你可以选择最多k个点,然后把你的牛任意分配在这k个点里。之后,每一头牛可以选择不动,也可以顺时针走d格并呆在那里。这样,它要耗费d的能量。通过合理选择点、合理分配牛、合理安排牛的走动,使得消耗的总能量最小。

      $nleq 1000,kleq 7,r_ileq 10^6$

    提示

      先证明一个小小的性质。

      然后断环为链,并参照BZOJ3675以及BZOJ1096的做法。

      注意初始化$dp_{0,i}$为$infty$。

  • 相关阅读:
    毕业面试试题汇总
    js获取系统日期
    非常酷的3D翻转相册展示特效
    CSS 替换元素和非替换元素 行内非替换元素
    怎样在linux下编写C程序并编译执行
    库和框架的区别
    转载:em(倍)与px的区别
    RPMForge介绍及安装
    linux下安装jdk和配置环境变量
    PCI PCI-X PCI-E介绍
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/DP-Slope-Optimalize.html
Copyright © 2011-2022 走看看