专栏文章
四边形不等式和决策单调性
算法·理论参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miouzxry
- 此快照首次捕获于
- 2025/12/03 01:35 3 个月前
- 此快照最后确认于
- 2025/12/03 01:35 3 个月前
四边形不等式的定义
当对于满足时,
称满足四边形不等式。
第一类DP优化
决策单调性
指的是的决策点满足单调性,
相当于 随着 的增大而增
当新加入的是新的决策点时,相当于:
因而后面的连续一段的决策点都为
因此新加入元素,原尾部元素变为
算法实现
单调队列 维护决策集合P
单调队列中储存了一个三元组(l,r,j),表示,从l到r的最优决策点都为
对于每一个,执行下面操作:
-
删除无效队头:当队头为(l,r,j),若,说明当前对头对于答案无效,弹出对头。否则将l设为i
-
取出队头的最优决策点,更新当前
-
插入新元素:(1) 取出当前队尾(2) 若,则删除队尾,回到(1)操作。(3) 用二分在中找出,使前此决策优,后(包含) 更优,将修改为(4) 将 放入队尾
时间复杂度。
代码实现
CPPint 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));
}
}
分治
假设已知的最优决策在上。
定义,设的最优决策为,根据决策单调性,可知的最优决策在内,的最优决策在内。
于是将问题分割成了同类型的规模更小的问题,便可递归分治。
时间复杂度
代码实现
CPPint 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优化
决策单调性
当 ,满足:
且
代码实现
CPPint 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';
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...