斜率优化dp小结

单调队列优化

在写斜率优化之前,我们来回顾一下单调队列优化的dp

1. 对于如下形式的dp方程

dp[i]=min{dp[j]+f(j)}(0<j<i)

我们直接用一个变量维护(0, i)中dp[j] + f(j)的最小值即可

2.对于如下形式的dp方程

dp[i]=min{dp[j]+f(j)}(i?m<j<i)

我们可以用一个单调队列维护一个(i - m, j)中dp[j] + f(j)的最小值,然后做到O(1)转移。

斜率优化

基本形式

但是对于形如

dp[i]=min{dp[j]+f(i,j)}

的方程,无法做到O(1)计算dp[j]+f(i,j)的最小值,这时就需要斜率优化这个技巧来解决这个问题了。

令k < j < i,当我们更新dp[i]时,如果有dp[j] + f(i, j) 比dp[k] + f(i, k)更优,则有dp[j] + f(i, j) - (dp[k] + f(i, k) < 0,对于这个不等式如果能够化解成如下形式

Y(j)?Y(k)X(j)?X(k)<f(i)

我们就能通过斜率优化这个dp了。

让我们来举一个例子: hdu3507 dp方程为

dp[i]=min{dp[j]+M+(sum[i]?sum[j])2(0<j<i)}

令k < j < i,当有

dp[j]+M+(sum[i]?sum[j])2?(dp[k]+M+(sum[i]?sum[k])2)<0

从j转移到i, 比从k转移到i更优,变换此不等式可得:

(dp[j]+sum[j]2)?(dp[k]+sum[k]2)sum[j]?sum[k]<2sum[i]

令Y(i)=dp[i]+sum[i]2, X(i)=sum[i], f(i)=2sum[i]则将此不等式化解为上述形式。

优化方法:

可以发现,若满足Y(j)?Y(k)X(j)?X(j)<f(i)则j转移到i,比k转移到i更优,如果我们把(X(j), Y(j)), (X(k), Y(k))当成平面上的两个点Pj, Pk,这个不等式的含义即为若PjPk?→??的斜率<f(i)则,从j转移更优。

令grad(i, j)表示PiPj?→??的斜率,现在我们假设grad(i,j) < grad(j, k),若grad(i, j) < f(I),则i比j更优,若grad(i, j) > f(I), 则grad(j, k) > f(I),那么从k转移比从j转移更优,当grad(i, j) < grad(j, k)的时候,无论如何j转移到i都不会是最优。而这种情况恰好对应下图

所以这种情况时,我们可以直接把j点删除,最后能够转移的点集只会存在这种图形,

所以最后我们维护一个上凸集即可。

但是此时我们还是没有解决最终问题,如何才能找到转移到i点的最优的点呢。可以发现最后的点集一定是一个凸集,也就是斜率单调!!这样对于k < j, grad(j,k) < f(i),时更优,从图形特点我们可以发现如果j比k优,那么j点比所有比k小的点都优,所以对于每一个f(i),我们维护一个所有比i点小的凸集,二分查找斜率比f(i)小的编号最大的点,就是最优的转移点。如果f(i)也满足单调性,比如这道题,我们还可以直接维护一个单调队列就能解决这个问题。

分治做法

对于f(i)单调的这种情况,除了使用单调队列优化的斜率优化做,我们还有另外一种分治的做法,但是复杂度会变成O(nlogn) 比O(n)差。

当f(i)单调的时候,我们可以发现若a > b,则f(a) > f(b),设转移到a的最优点是c,转移到b的最优点是d,一定有c > d。也就是转移到a的最优点一定大于等于转移到b的最优点。考虑这样的分治

void dfs(int l, int r, int dl, int dr) {
    //[l,r]表示现在更新[l,r]区间dp[i]的最优值
    //用j -> f(i),表示j是更新f(i)最优值的最优点
    //那么[dl,dr]表示更新dp([l,r])的点,一定在[dl,dr]范围内
    int mid = (l + r) >> 1;
    int dm = dl;
    int g = inf;
    for (int i = dl; i <= dr; i++) {
        if(g < dp[i] + f(i, mid)) {
            g = dp[i] + f(i, mid);//记录更新dp[mid]的最优
            dm = i;//记录更新dp[mid]的最优点
        }
    }
    dp[mid] = g; //更新dp[mid]的值
    //因为上文叙述的单调性,
    //更新[l,mid-1]的最优点,一定在[dl,dm]范围内
    if(l < mid) dfs(l, mid - 1, dl, dm);
    //更新[mid+1,r]的最优点,一定在[dm,dr]范围内
    if(mid < r) dfs(mid + 1, r, dm, dr);
}

可以发现这个分治比起斜率优化,不仅写起来方便很多,并且适用的范围也更广。这个做法不局限于斜率单调,可以发现只要满足c是更新f(a)的最优点,d是更新f(b)的最优点,若a > b 一定有 c > d,则可以有这个分治做。

PS:

这个做法是我在codeforces 674E,跟Claris神犇的代码学会的solution,在此特地感谢Claris.这个做法着实是非常的劲啊!多一个log,但是换来编码复杂度和通用性更广的解法。

时间: 2024-10-02 16:21:33

斜率优化dp小结的相关文章

bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜.所以,一段路必须在同一天中走完. Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小. 帮助Pine求出最小方差是多少. 设方差是v,可以证明,v×m^2是一个整数.为了避免精度误差,输出结果时输出v×m^2. In

[bzoj 1911][Apio 2010]特别行动队(斜率优化DP)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 分析: 首先可以的到裸的方程f[i]=max{f[j]+a*(Si-Sj)^2+b*(Si-Sj)+c} 0<j<i 简化一下方程,我们知道对于一次项,最后结果肯定是b*Sn 所以可以写成f[i]=max{f[j]+a*(Si-Sj)^2+c} 0<j<i 我们不妨设0<x<y<i,且x比y优 即f[x]+a*(Si-Sx)^2+c>f[y]+a*

hdu 2993 MAX Average Problem (斜率优化dp入门)

MAX Average Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5855    Accepted Submission(s): 1456 Problem Description Consider a simple sequence which only contains positive integers as

hdu3507之斜率优化DP入门

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 4780    Accepted Submission(s): 1437 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antiqu

bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏.由于地形的不同,在不同工厂建立仓库的费用可能是不同的.第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci.对

HDU3045 Picnic Cows(斜率优化DP)

Picnic Cows Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2192    Accepted Submission(s): 675 Problem Description It’s summer vocation now. After tedious milking, cows are tired and wish to t

BZOJ 1096 [ZJOI2007]仓库建设 斜率优化dp

1096: [ZJOI2007]仓库建设 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1096 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场

HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)

题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小.一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0. 析:DP状态方程很容易想出来,dp[i][j] 表示前 j 个数分成 i 组.但是复杂度是三次方的,肯定会超时,就要对其进行优化. 有两种方式,一种是斜率对其进行优化,是一个很简单的斜率优化 dp[i][j] = min{dp[i-1][k] - w[k] + sum[k]*sum[k] - sum[k]*sum[

BZOJ 3156: 防御准备 斜率优化DP

3156: 防御准备 Description Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小的战线花费值. Sample Input 10 2 3 1 5 4 5 6 3 1 2 Sample Output 18 HINT 1<=N<=10^6,1<=Ai<=10^9 题解: 斜率优化DP: 首先将数组倒置 设定dp[i] 为前i的点的最优答案 易得 dp[i] = min{dp[j