四边形不等式和决策单调性
四边形不等式的定义
当对于
称
第一类DP优化
决策单调性
指的是
相当于
当新加入的
因而后面的连续一段的决策点都为
因此新加入元素
算法实现
单调队列 维护决策集合P
单调队列中储存了一个三元组(l,r,j),表示,从l到r的最优决策点都为
对于每一个
- 删除无效队头:当队头为(l,r,j),若
r\le i-1 ,说明当前对头对于答案无效,弹出对头。否则将l设为i - 取出队头的最优决策点,更新当前
f_i -
插入新元素:
i (1) 取出当前队尾
(l,r,j) (2) 若
f[l]+w(i,l)\le f[j]+w(j,l) ,则删除队尾,回到(1)操作。(3) 用二分在
[l,r] 中找出pos ,使pos 前此决策优,pos 后(包含pos )i 更优,将(l,r,j) 修改为(l,pos-1,j) (4) 将
(pos,n,i) 放入队尾
时间复杂度
代码实现
int n;
int l,r,q[N];
int L[N],R[N];
int w(int x,int y);
void solve(){//写法一,加入f[0]
l=1,r=1,q[1]=0;
L[0]=1,R[0]=n;
for(int i=1;i<=n;i++){
while(l<=r && R[q[l]]<i) //弹出队首无用项
l++;
f[i]=w(q[l],i);
while(l<=r && w(i,L[q[r]])<=w(q[r],L[q[r]]))//弹出队尾无用项
r--;
int ll=L[q[r]],rr=n+1;
while(ll<rr){//二分获得pos
int mid=ll+rr>>1;
if(w(i,mid)<=w(q[r],mid)) rr=mid;
else ll=mid+1;
}
if(ll>n) continue;
R[q[r]]=ll-1;
q[++r]=i;
L[i]=ll,R[i]=n;
}
}
void solve(){//写法二,不加入f[0]
l=1,r=0;
for(int i=1;i<=n;i++){
int ans=n+1;
L[q[r]]=max(L[q[r]],i);
while(l<=r && w(i,L[q[r]])>=w(q[r],L[q[r]]))//弹出队尾无用项
r--;
if(l<=r && w(i,R[q[r]])>=w(q[r],R[q[r]])){
ans=R[q[r]]+1;
int ll=L[q[r]],rr=R[q[r]];
while(ll<=rr){//二分获得pos
int mid=ll+rr>>1;
if(w(i,mid)>=w(q[r],mid)) ans=mid,rr=mid-1;
else ll=mid+1;
}
R[q[r]]=ans-1;
}
if(l>r) q[++r]=i,L[i]=i,R[i]=n;
if(ans!=n+1) q[++r]=i,L[i]=ans,R[i]=n;
while(l<=r && R[q[l]]<i) //弹出队首无用项
l++;
L[q[l]]=i;
f[i]=max(f[i],w(q[l],i));
}
}
分治
假设已知
定义
于是将问题分割成了同类型的规模更小的问题,便可递归分治。
时间复杂度
代码实现
int w(int j,int i);
void DP(int l,int r,int ll,int rr) {
int mid=l+r>>1,k=ll;
for (int j=ll;j<=min(rr,mid-1);j++)//寻找当前决策点
if (w(j,mid)<w(k,mid)) k=j;
f[mid]=w(k,mid);
if(l<mid) DP(l,mid-1,ll,k);
if(r>mid) DP(mid+1,r,k,rr);
}
第二类DP优化
决策单调性
当
代码实现
int w(int j,int i);
for(int i=1;i<=n;i++) f[i][i]=f[i+1][i]=f[i][i-1]=0,p[i][i]=i;
for(int len=2;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j=i+len-1;
for(int k=p[i][j-1];k<=p[i+1][j];k++){
if(f[i][j]>f[i][k-1]+f[k+1][j]+w(i,j)){
f[i][j]=f[i][k-1]+f[k+1][j]+w(i,j);
p[i][j]=k;
}
}
}
}
cout<<f[1][n]<<'\n';