一类1D/1D动态规划方程的三种优化情况 单调队列优化 斜率优化 决策单调性优化

众所周知,DP优化有单调队列优化、数据结构优化、矩阵快速幂优化、斜率优化、四边形不等式优化、决策单调性优化、凸优化等。本文讲解关于一类DP方程的三种优化情况。

f [ i ] = min ⁡ { f [ j ] + w ( i , j ) } f[i]=\min\{f[j]+w(i,j)\} f[i]=min{f[j]+w(i,j)}

其中 j ∈ [ l [ i ] , r [ i ] ] j\in [l[i],r[i]] j[l[i],r[i]] l [ i ] l[i] l[i] r [ i ] r[i] r[i]单调不减。 min ⁡ \min min可换为 max ⁡ \max max,方法相同。

w ( i , j ) w(i,j) w(i,j) j j j无关

对于 j , k ∈ [ [ l [ i ] , r [ i ] ] ( j &lt; k ) j,k\in [[l[i],r[i]](j&lt;k) j,k[[l[i],r[i]](j<k),若 f [ k ] f[k] f[k]不比 f [ j ] f[j] f[j]更劣(更大),则 j j j k k k以后的更新都不会有任何贡献,因为有 j j j的地方就有 k k k,且完全可以选 k k k而不选 j j j。因此用一个单调队列维护当前有用的转移下标即可。

时间复杂度 O ( n ) O(n) O(n)

w ( i , j ) w(i,j) w(i,j)只含 i i i的多项式、 j j j项和 i j ij ij

时间复杂度为 O ( n ) O(n) O(n) O ( n log ⁡ n ) O(n\log n) O(nlogn)

w ( i , j ) w(i,j) w(i,j)满足四边形不等式

四边形不等式 w ( i + 1 , j ) − w ( i , j ) ≥ w ( i + 1 , j + 1 ) − w ( i , j + 1 ) w(i+1,j)-w(i,j)\ge w(i+1,j+1)-w(i,j+1) w(i+1,j)w(i,j)w(i+1,j+1)w(i,j+1)
这个性质说明,对于更大的 j j j w ( ) w() w()随着 i i i增长的速度越慢。因此对于 k &gt; j k&gt;j k>j,如果从 k k k转移不劣于从 j j j转移,那么 j j j k k k转移以后就没用了,因为随着 i i i的增加 w ( i , j ) w(i,j) w(i,j)只会比 w ( i , k ) w(i,k) w(i,k)越来越差。即 f [ i ] f[i] f[i]的决策点是单调右移的,即决策单调性

一般有两种方法来实现:

栈+二分

考虑每个决策点能更新哪些状态。我们枚举 1 1 1 n n n的决策点来更新后面的状态。由于决策单调性,每次更新后,决策点数列是单调不减的。因此每次更新的位置是一个区间 [ k i , n ] [k_i,n] [ki,n]。于是我们用一个栈维护从左到右的连续相同的决策点块,每次更新时从栈顶开始检查,如果新决策比原决策块完全更优就把原决策块弹掉,否则二分原决策块区间找到从哪个点开始新决策更优。最后将新决策块入栈。

每个决策最多入栈、出栈一次,因为用了二分,时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

struct decis {
	int a, l, r; // 决策点位置,决策块管辖区间
}S[maxn];
int top;

//...
{
	top = 0;
	S[top++] = (decis){0, 0, n-1}; // 第一个决策块
	for(int i = 1; i < n; i++) {
		while(top) {
			decis ctop = S[top-1];
			int ftop = f[ctop.a] + calc(), fnew = f[i] + calc(); //calc()为分别用ctop.a和i更新ctop.l的代价
			if(ftop > fnew) top--; else break;
		}
		if(top) {
			int l = S[top-1].l, r = S[top-1].r+1;
			while(l < r) {
				int mid = l + r >> 1;
				int ftop = f[S[top-1].a] + calc(), fnew = f[i] + calc();  //calc()为分别用S[top-1].a和i更新mid的代价
				if(ftop > fnew) r = mid; else l = mid+1;
			}
			// 此时l的值是第一个新块较优的位置
			if(l <= S[top-1].r) {
				decis o = S[top-1]; top--;
				S[top++] = (decis){o.a, o.l, l-1};
			}
			if(l <= n-1) S[top++] = (decis){i, l, n-1};
		}else S[top++] = (decis){i, k-1, n-1};
	}
	for(int i = 0; i < top; i++) for(int j = S[i].l; j <= S[i].r; j++) f[j] = f[S[i].a] + calc();
}

分治

考虑分治处理每个点的决策点。设当前在处理 [ l , r ] [l,r] [l,r]的决策点,并已知可能的决策点区间为 [ L , R ] [L,R] [L,R]。设 m i d = l + r 2 mid=\frac{l+r}{2} mid=2l+r,则先暴力求出 m i d mid mid的决策点 p p p(范围肯定是 [ L , m i d ] [L,mid] [L,mid]),然后分治处理两边,显然 [ l , m i d ] [l,mid] [l,mid]的决策点在 [ L , p ] [L,p] [L,p],而 [ m i d + 1 , r ] [mid+1,r] [mid+1,r]的决策点在 [ p , R ] [p,R] [p,R]。复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn)

w ( i , j ) w(i,j) w(i,j)满足四边形不等式和区间单调性

Upd on 2018.11.26

区间单调性 对于所有区间 [ i , j ] [i,j] [i,j]包含 [ i ′ , j ′ ] [i&#x27;,j&#x27;] [i,j],有 w ( i , j ) &gt; w ( i ′ , j ′ ) w(i,j)&gt;w(i&#x27;,j&#x27;) w(i,j)>w(i,j)

w ( i , j ) w(i,j) w(i,j)满足四边形不等式和区间单调性,则决策点满足区间单调性。因此枚举决策点的时候只用从之前的决策点之间枚举。类似四边形不等式优化区间DP,复杂度从 O ( n 3 ) O(n^3) O(n3)降为 O ( n 2 ) O(n^2) O(n2)

例题:IOI2000 邮局

练习题

BZOJ3675 POJ1160 BZOJ1492 HDU3480 BZOJ2726 HDU2829 BZOJ1791 HDU3516

2018.11.30 DP凸优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值