斜率优化DP 与数形结合思想

前言

最近才入了DP优化的大坑……
发现斜率优化DP还是很有用的
下面会结合一道例题,同时讲解斜率优化DP

正文

先看一下例题:HDU3507
题目大意:有一串数列,要把它分割成若干段
每一段的代价是 这一段所有数的和 的平方 再加上常数M
求最小的代价和。

DP很好推啊,f[i]表示前i个数字的最小代价和

f[i]=Min{f[j]+(s[i]s[j])2}+M

其中s[]是原数列的前缀和
按如下方式转化:
f[i]=Min{f[j]+s[i]22s[i]s[j]+s[j]2}+M

f[i]=Min{f[j]2s[i]s[j]+s[j]2}+M+s[i]2

k=2s[i]x=s[j]y=f[j]+s[j]2
由于 Min{} 外面的部分只与 i 有关,可以先不考虑
设里面的部分为 b ,则有:
b=kx+y
y=kx+b

你会发现,这不就是一条直线嘛
我们来好好思考一下这条直线与DP之间的联系:
前面已求得的每个状态j都被抽象成二维平面上的一个点(x,y)
b是我们要求的最小值,而斜率k只与i有关
也就是说,要过所有的点做一条斜率为k的直线,
所有直线截距的最小值就是我们的b
如下图:
斜率优化DP 与数形结合思想_第1张图片

不难发现,能取到最小截距的状态j(x,y)一定在当前的 下凸壳 上
再加上s[j]随j递增(即x坐标递增)
我们就可以用凸包算法Andrew动态维护一个下凸壳
本题又有一个很好的性质,就是斜率k也是递增的
这导致了每次选取的状态j也是递增的
那么就可以用一个指针记录上次选取的状态,每次往后找即可
时间复杂度O(n)

扩展讨论

上述问题中,如果斜率k不递增,那就只能在凸壳上二分了:
通过判断 mid左右两侧直线的斜率 与k的大小关系 来缩小范围
时间复杂度O(nlogn)

如果题目再恶心一点,连新加入点的x都不递增呢?
那就需要写一个Splay维护凸壳,或者CDQ分治
时间复杂度O(nlogn)

示例程序

#include
#include
#include
#define LL long long
using namespace std;
const int maxn=500005;
int n,m;
LL s[maxn],f[maxn];
#define nc getchar
inline int red(){
    int tot=0,f=1;char ch=nc();
    while (ch<'0'||'9'if (ch=='-') f=-f;ch=nc();}
    while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=nc();
    return tot*f;
}
struct point{
    LL x,y;
    point() {}
    point(LL a,LL b):x(a),y(b) {}
    point operator-(const point&b) {return point(x-b.x,y-b.y);}
}stk[maxn];
typedef point vec;
LL cross(vec a,vec b){
    return a.x*b.y-b.x*a.y;
}
LL getb(point a,LL k){
    return -a.x*k+a.y;
}
int main(){
    while (scanf("%d%d",&n,&m)==2){
        for (int i=1;i<=n;i++) s[i]=s[i-1]+red();
        memset(f,63,sizeof(f));
        f[0]=0;
        int len=1,now=1;stk[1]=point(0,0);
        for (int i=1;i<=n;i++){
            LL k=2*s[i];
            while (now1],k)while (len>1&&cross(stk[len]-stk[len-1],a-stk[len-1])<=0){
                len--;if (now>len) now--;
            }
            stk[++len]=a;
        }
        printf("%lld\n",f[n]);
    }
    return 0;
}

总结

斜率优化DP的存在,再一次提醒我们数形结合的重要性
在OI中,类似的例子还有很多……
但是,在运用数形结合思想时,要注意“形”与“数”之间的联系
切勿将想法匆匆过一遍就用代码实现,容易搞混

你可能感兴趣的:(斜率优化DP,算法,数据结构心得,我的OI历程,DP,斜率优化DP,数形结合,动态规划)