四边形不等式与决策单调性

四边形不等式与决策单调性

四边形不等式

首先,给出四边形不等式的定义:

定义一

\(w(x,y)\) 是定义在整数集合上的二元函数,若对于定义域上的任意整数 \(a,b\) ,其中有 \(a<b\) ,都有:

\[w(a,b+1)+w(a+1,b) \ge w(a,b)+w(a+1,b+1) \]

则称函数 \(w\) 满足四边形不等式

定义二

\(w(x,y)\) 是定义在整数集合上的二元函数,若对于定义域上的任意整数 \(a,b,c,d\) ,其中有 \(a\le b\le c\le d\) ,都有:

\[w(a,d)+w(b,c) \ge w(a,c)+w(b,d) \]

则称函数 \(w\) 满足四边形不等式

方便记忆:交叉小于包含

简单证明一下定义二:

对于 \(a<c\) ,有

\[w(a,c+1)+w(a+1,c) \ge w(a,c)+w(a+1,c+1) \]

对于 \(a+1<c\) ,有:

\[w(a+1,c+1)+w(a+1+1,c)\ge w(a+1,c)+w(a+1+1,c+1) \]

两式相加得:

\[w(a,c+1)+w(a+2,c)\ge w(a,c)+w(a+2,c+1) \]

以此类推,对任意的 \(a\le b\le c\)

\[w(a,c+1)+w(b,c)\ge w(a,c)+w(b,c+1) \]

同理,对 \(a\le b\le c+1\) 得到的式子与上式相加,我们可以得到,对任意 \(a\le b\le c\le d\) ,有:

\[w(a,b)+w(b,c)\ge w(a,c)+w(b,d) \]

决策单调性

定义

形如 \(f[i]=min \{ f[j]+val(j,i) \} (0\le j\le i)\) 的状态转移方程,如果 \(p[i]\) 为状态 \(f[i]\) 的决策,并且数组 \(p\)\([1,N]\) 上单调不减,简称 \(f\) 具有决策单调性

还有一个性质,形如上述的状态转移方程中,若 \(val(j,i)\) 符合四边形不等式,那么 \(f\) 具有决策单调性。

证明:

\(\forall i\in [1,N],\forall j \in [0,p[i]-1]\),根据定义有:

\[f[p[i]]+val(p[i],i)\le f[j]+val(j,i) \]

\(\forall i^`\in [i+1,N]\),因为 \(val\) 满足四边形不等式,且 \(j<p[i]\le i<i^`\)

\[val(j,i^`)+val(p[i],i)\ge val(j,i)+val(p[i],i^`) \]

移项得:

\[val(p[i],i^`)-val(p[i],i)\le val(j,i^`)-val(j,i) \]

与第一个不等式相加,有:

\[f[p[i]]+val(p[i],i^`)\le f[j]+val(j,i^`) \]

看到最后的式子,即决策点 \(p[i]\) 一定不劣于决策点 \(j\) ,并且 \(j<p[i]\) ,即得证。

用法

显然,最简单的优化为将状态转移方程写作:

\[f[i]=min \{ f[j]+val(i,j) \} ( p[i-1]\le j\le i ) \]

缩小了决策范围,但这样做却不一定能更优,例如 \(p=\{ 1,1,1,1,1,1,1,1 \}\)

所以我们肯定存在其他方法。

当循环到某一个 \(i\) 时, 有可能 \(p=\{ j_1j_1j_2j_2j_2j_3j_3j_3j_4j_4j_5j_5j_5 \}\)

其中 \(j_1<j_2<j_3<j_4<j_5<i\)

当求解出 \(f[i]\) 后,我们即可以更新 \(p\) ,也就是找到一个点 \(k\) ,比较当它的决策点为 \(i\) 时与决策点为 \(p[k]\) 时的大小,若前者更优,那我们就把它和它之后所有点的决策换为 \(i\) ,即 \(p=\{ j_1j_1j_2j_2j_2j_3iiiiiii \}\)

这么做相当于我们实现了动态更新 \(p\) 数组。

但这个过程该如何实现呢?暴力的效率是相当低的,不能达到我们的优化目的。

考虑使用一个队列代替 \(p\) 数组,队列中保存若干个三元组 \((j,l,r)\) ,其中 \(j\) 为决策, \(l,r\) 为区间。

例如:

\(p=\{ j_1j_1j_2j_2j_2j_3j_3j_3j_4j_4j_5j_5j_5 \}\) 可以表示为 \((j_1,1,2)(j_2,3,5)(j_3,6,8)(j_4,9,10)(j_5,11,13)\)

当更新 \(i\) 的时候,发现 \((j_4,9,10)(j_5,11,13)\) 的左端点的决策都比 \(i\) 更劣,从队列中将其删去。但是 \((j_3,6,8)\) 左端点比 \(i\) 更优,右端点比 \(i\) 劣,那我们就二分找到一个中间点更新即可。

如何通过这个队列维护求解 \(f\) 数组,实际上它是个动态更新的过程,但显然前面已经使用过的都是我们不需要的,每次用完过后将其出队,这样每次更新 \(f\) 的值我们就只需要取出队头即可。

总结

上述过程有些凌乱,此部分梳理一下其具体过程

  • 对于每个 $i\in [1,N] $ ,我们执行一下操作:

    • 检查队头 \(( j_0,l_0,r_0 )\) ,若 \(r_0<i\) ,删除队头,否则:\(l_0=i\)
    • 取出队头 \(j\) ,作为最优决策,算出 \(f[i]\)
    • 插入决策 \(i\)
      • 取出队尾 \((j_t,l_t,r_t)\)
      • 如果对于 \(f[l_t]\)\(j_t\) 劣于 \(i\) ,即 \(f[i]+val(i,l_t) \le f[j_t]+val(j_t,l_t)\) ,删除队尾,记 \(pos=l_t\)
      • 如果对于 \(f[r_t]\)\(j_t\) 优于 \(i\) ,则将 \((i,pos,N)\) 插入队尾,结束该过程。
      • 如果上述两点都不满足,则在 \([l_t,r_t]\) 中进行二分,找到最小 \(pos\) 满足 \(f[i]+val(i,pos) \le f[j_t]+val(j_t,pos)\) ,则将 \((j_t,l_t,pos-1),(i,pos,N)\) 插入队尾。
posted @ 2021-07-09 08:39  ╰⋛⋋⊱๑落叶๑⊰⋌⋚╯  阅读(126)  评论(1编辑  收藏  举报