关于决策单调性优化动态规划

今天考场上突现决策单调性

原本对这个算法表示摒弃的本弱突然被打击了

于是来学习学习...

 

原理

我们只考虑$1D\;|\;1D$的动态规划...

同时,我们讨论这么一类$dp$:$f[i] = min(f[j] + w(j, i))(1 \leqslant j \leqslant i - 1)$

($max$同理)

我们记$w(i, j)$表示从$i$转移到$j$的代价

 

决策单调性是指对于$a < b < c < d$

如果$c$从$b$转移过来比从$a$转移过来更优

那么$d$从$b$转移过来比从$a$转移过来更优

用两个不等式来表达:

$$f[b] + w(b, c) \leq f[a] + w(a, c)...(1)$$

$$f[b] + w(b, d) \leq f[a] + w(a, d)...(2)$$

如果我们有$$w(b, d) - w(b, c) \leq w(a, d) - w(a, c)...(3)$$

那么我们就能由$(1) + (3)$得到$(2)$

考虑对$(3)$式化简,即$$w(b, d) + w(a, c) \leq w(a, d) + w(b, c)...(4)$$

这就是著名的四边形不等式

 

如果我们考虑用图形来表达,那么可以简记为“交叉”和“包含”的关系

这张图十分的形象

 

一般而言,$1D \;|1D$决策单调性的特点是没有特点

大致意思是,如果存在一个$dp$方程满足$1D\;|\;1D$

但是无法用斜率优化 / 前缀和 / $wqs$二分 / 数据结构优化...那么就可以考虑决策单调性

 

比较著名的例题

$[HNOI2008]$玩具装箱

非常显然的有$f[i] = min(f[j] + (i - j - 1 - L + s[i] - s[j])^2) (0 \leqslant j < i)$

令$w(j, i) = (i - j - 1 - L + s[i] - s[j])^2$

我们考虑证明$w(a, c) + w(b, d) \leq w(a, d) + w(b, c)$

$w(a, c) + w(b, d) = (c - a - L + s[c] - s[a])^2 + (d - b - L + s[d] - s[b])^2$

$w(a, d) + w(b, c) = (d - a - L + s[d] - s[a])^2 + (c - b - L + s[d] - s[c])^2$

对比上下两式,我们就能证明了

式子太长了不写了

 

我们引入一道平时训练的题,即$CF868F...$

非常明显的,我们设$f[i][j]$表示$1 \sim i$中,划分了$j$段的最小代价

那么有$f[i][k] = min(f[j][k - 1] + w(j, i))(1 \leqslant j \leqslant i)$

我们考虑证明$w(b, d) + w(a, c) \leq w(b, c) + w(a, d)$,就能证明决策单调性

我们设第$i$种颜色在段$[a, b)$中出现了$x$次,在$[b, c)$中出现了$y$次,在$[c, d)$中出现了$z$次

那么$w(b, d) + w(a, c) = \binom{x + y}{2} + \binom{y + z}{2}$

同时$w(a, d) + w(b, c) = \binom{x + y + z}{2} + \binom{y}{2}$

左式$ = x^2 + 2y^2 + z^2 + 2xy + 2yz - x - 2y - z$

右式$ = x^2 + 2y^2 + z^2 + 2xy + 2yz + 2xz - x - 2y - z$

那么如果左式$\leq$右式,那么有$-x-2y-z \leq 2xz - x - 2y - z$

这显然成立,由于对每个颜色都满足这个不等式,因此四边形不等式是成立的

所以证明决策单调性没有想象中的那么困难...

 

实现决策单调性

我们分两种情况来讨论,我们考虑有$n$个决策点和$m$个被决策点

 

第一种情况,决策点和被决策点互相独立(yjq教会了我分治,却没有告诉我它的作用是有限的)

即,被决策点在将来不会成为决策点

这时,我们可以考虑用分治来解决,复杂度为$O(n \log m + m)$

void solve(int l, int r, int L, int R) {   
    if(l > r) return;
    //现在我们知道[L, R]的点可以决策[l, r]的点
    int pos = -1, mid = (l + r) >> 1;
    //我们寻找出mid的最优决策点
    for(int i = L; i <= min(R, mid - 1); i ++)
        if(g[i] + w(i, mid) < f[mid]) 
            f[mid] = g[i] + w(i, mid), pos = i;
    //g与f无关!!!
    //w(i, j)表示从i转移到j的代价
    //找出mid的最优决策点后
    //[l, mid - 1]的决策点区间落在[L, pos]中
    //[mid + 1, r]的决策点区间落在[pos, R]中
    solve(l, mid - 1, L, pos);
    solve(mid + 1, r, pos, R);
    //递归即可
}

 

 

同时在这时,如果$w(i, j)$不好$O(1)$的计算

但是,用类似于莫队的方式十分好维护

那么我们仍然可以在$O(n \log m + m \log m)$的时间内解决这个问题

int nl, nr;
int w(int i, int j) {
    while(nl > i) ...;
    while(nl < i) ...;
    while(nr > j) ...;
    while(nr < j) ...;
    return ...;
}

void solve(int l, int r, int L, int R) {
    if(l > r) return;
    int pos = -1, mid = (l + r) >> 1;
    for(int i = L; i <= min(R, mid - 1); i ++)
        if(g[i] + w(i, mid) < f[mid]) 
            f[mid] = g[i] + w(i, mid), pos = i;
    solve(l, mid - 1, L, pos);
    solve(mid + 1, r, pos, R);
}

复杂度的证明:分治树总共有$log$层,在每一层内两个指针把决策点树和被决策点树都扫了一遍

 

第二种情况,决策点和被决策点互相影响

即,被决策点在将来会成为决策点

这时,我们可以采用二分 + 单调栈来优化,复杂度和分治同样,为$O(n \log m + m)$

 

我们可以用经常举的例子,一开始

$1 \sim n$对于$1 \sim i$内的决策点在$i = 1$时

一定长成这个样子:111111111111111111111111111111111111111111

我们可以确定出$2$的最优取值,加入$2$

这时,我们可以发现,$1 \sim n$的决策点会更变为这个样子

11111111111111111111222222222222222222222222

这时,我们又可以确定出$3$的最优取值,然后就会变成

11111111111111111111222222222222333333333333

依次类推,每次寻找新的分界的过程可以二分

 

特别的,以$3$为例,如果加入$3$后,变成了

1111111111111111111133333333333333333333

这时,我们需要弹掉$2$的决策区间,用栈可以维护

也就是说,用栈+二分来维护即可

 

略微的比分治要难写一点

//二分出当前可以转移到哪些点
int find(int x) {
    int l = lp[top], r = n;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(w(x, mid) < w(go[top], mid)) r = mid - 1;
        else l = mid + 1;
    }
    return l;
}

void solve() {
    int tra = top = 1;
    lp[1] = 1; go[1] = 0;
    //lp : 当前栈元素的转移区间的左端点
    //go : 当前栈元素的转移区间由谁来转移
    for(ri i = 1; i <= n; i ++) {
        if(i == lp[tra + 1]) tra ++;
        dp[i] = w(go[tra], i);
        while(w(i, lp[top]) < w(go[top], lp[top])) top --;
        int tmp = find(i);
        if(tmp <= n) lp[++ top] = tmp, go[top] = i;
    }
}

 

决策单调性的题目并不多,写几道就差不多知道套路了

而且你知道了是决策单调性就简单了不少

 

习题

还是给出几道题目供大家练手吧...

$[HNOI2008]$  玩具装箱

$[NOI2009]$  诗人小G

$51nod1789$  跑的比谁都快

$bzoj5125$  小Q的书架

$CF868F$  Yet Another Minimization Problem 

$51nod1488$  帕斯卡小三角(存在决策单调性)

 

一些有趣

 咕了

posted @ 2018-10-29 19:56  remoon  阅读(1561)  评论(0编辑  收藏  举报