四边形不等式
四边形不等式
引入:
动态规划中,经常遇到形如下式的状态转移方程:
$$m(i,j)=min {m(i,k-1),m(k,j)}+w(i,j)(i≤k≤j)(min也可以改为max)$$
上述的 \(m(i,j)\) 表示区间 \([i,j]\) 上的某个最优值。\(w(i,j)\) 表示在转移时需要额外付出的代价。该方程的时间复杂度为 \(O(N^3)\)
下面我们通过四边形不等式来优化上述方程,首先介绍什么是“区间包含的单调性”和“四边形不等式”
算法介绍:
-
区间包含的单调性:如果对于 \(i≤i'<j≤j'\),有 \(w(i',j)≤w(i,j')\),那么说明w具有区间包含的单调性。(可以形象理解为如果小区间包含于大区间中,那么小区间的\(w\)值不超过大区间的\(w\)值)
-
四边形不等式:如果对于 \(i≤i'<j≤j'\),有 \(w(i,j)+w(i',j')≤w(i',j)+w(i,j')\),我们称函数\(w\)满足四边形不等式。(可以形象理解为两个交错区间的w的和不超过小区间与大区间的\(w\)的和)
定理:
1. 如果上述的 \(w\) 函数同时满足区间包含单调性和四边形不等式性质,那么函数 \(m\) 也满足四边形不等式性质
我们再定义 \(s(i,j)\) 表示 \(m(i,j)\) 取得最优值时对应的下标(即 \(i≤k≤j\) 时,\(k\) 处的 \(w\) 值最大,则 \(s(i,j)=k)\)。此时有如下定理。
2. 假如 \(m(i,j)\) 满足四边形不等式,那么 \(s(i,j)\) 单调,即 \(s(i,j)≤s(i,j+1)≤s(i+1,j+1)\)。
运用:
好了,有了上述的两个定理后,我们发现如果w函数满足区间包含单调性和四边形不等式性质,那么有:
即原来的状态转移方程可以改写为下式:
$$m(i,j)=min{m(i,k-1),m(k,j)}+w(i,j)(s(i,j-1)≤k≤s(i+1,j))(min也可以改为max)$$
例题:
#include<bits/stdc++.h>
using namespace std;
const int N=3e3+5,M=3e2+5;
int n,m,a[N],dp[N][M],w[N][N],d[N][M];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int l=1;l<=n;l++){
w[l][l]=0;
for(int r=l+1;r<=n;r++) w[l][r]=w[l][r-1]+a[r]-a[l+r>>1];
}
sort(a+1,a+n+1); memset(dp,0x3f3f3f3f,sizeof(dp)); dp[0][0]=0;
for(int j=1;j<=m;j++){
d[n+1][j]=n;
for(int i=n;i>=1;i--){
int minn=0x3f3f3f3f,minid;
for(int k=d[i][j-1];k<=d[i+1][j];k++){
if(dp[k][j-1]+w[k+1][i]<minn) minn=dp[k][j-1]+w[k+1][i],minid=k;}
dp[i][j]=minn,d[i][j]=minid;
}
}
cout<<dp[n][m]<<endl;
system("pause");
return 0;
}