环形与后效性处理
环形结构上的动态规划问题
在许多环形结构问题中,我们都能通过枚举法,选择一个位置把环断开,变成线性结构进行计算,最后根据每次枚举的结果求出答案。我们把能用上述枚举方式求解的环形问题称为“可拆解的环形问题”,这也是本节的主要研究对象。我们的目标是采取适当策略避免枚举,从而降低时间复杂度。
通常来说,我们解决环形问题的方式有两种:
-
执行两次DP
-
破环为链
下面我们将结合例题分别介绍这两种方法
执行两次DP
先来考虑一个“简化版”:假设第
用
状态转移方程就是:
dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]);
dp[i][j][1]=max(dp[i-1][j-1][0],dp[i-1][j-1][1]+u[i]);
初值:
答案:
但问题是第
强制让第
状态转移方程如上。
初值:
答案:
具体来说,我们可以先将第
ps:此题可用滚动数组优化空间
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,b,ans=0;
int f[2][3835][2],u[3835];
signed main(){
cin>>n>>b;
memset(f,-0x3f,sizeof(f));
f[1][0][0]=f[1][1][1]=0;
for(int i=1;i<=n;i++) cin>>u[i];
for(int i=2;i<=n;i++){
f[i&1][0][0]=0;
for(int j=1;j<=i;j++){
f[i&1][j][0]=max(f[(i-1)&1][j][0],f[(i-1)&1][j][1]);
f[i&1][j][1]=max(f[(i-1)&1][j-1][0],f[(i-1)&1][j-1][1]+u[i]);
}
}
ans=max(f[n&1][b][0],f[n&1][b][1]);
memset(f,-0x3f,sizeof(f));
f[1][1][1]=u[1];f[1][0][0]=0;
for(int i=2;i<=n;i++){
f[i&1][0][0]=0;
for(int j=1;j<=i;j++){
f[i&1][j][0]=max(f[(i-1)&1][j][0],f[(i-1)&1][j][1]);
f[i&1][j][1]=max(f[(i-1)&1][j-1][0],f[(i-1)&1][j-1][1]+u[i]);
}
}
ans=max(ans,f[n&1][b][1]);
cout<<ans;
return 0;
}
破环为链
题目描述
环上有
解法
断环为链的思想可以简述为:对于一个长度为
我们在任意位置(例如仓库
度为
对于原来环形公路上的任意两座仓库
如果
综上所述,原问题可以等价转化为:长度为
我们可以枚举
#include <bits/stdc++.h>
using namespace std;
int n,ans;
int a[2000002];
deque<int> q;
int main() {
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i+n]=a[i];
}
q.push_back(1);
for(int i=2;i<=2*n;i++){
while(q.size()&&i-q.front()>n/2){
q.pop_front();
}
int j=q.front();
ans=max(ans,a[i]+i+a[j]-j);
while(q.size()&&a[q.back()]-q.back()<=a[i]-i){
q.pop_back();
}
q.push_back(i);
}
cout<<ans;
return 0;
}
有后效性的状态转移方程
从最初学习DP开始,我们就多次强调,“阶段”是动态规划的三要素之一,“无后效性”是应用动态规划算法的三前提之一。事实上,在一些题目中,当我们根据题目的关键点抽象出“状态维度”,并设计出状态表示和状态转移方程后,却发现这道形似DP的题目不满足“无后效性”这一基本条件——部分状态之间互相转移、互相影响,构成了环形,无法确定出一个合适的DP“阶段”,从而沿着某个方向执行递推。
事实上,我们可以把动态规划的各状态看作未知量,状态的转移看作若干个方程。如果仅仅是“无后效性”这一条前提不能满足,并且状态转移方程都是一次方程,那么我们可以 不进行线性递推,而是用高斯消元直接求出状态转移方程的解。
在更多的题目中,动态规划的状态转移“分阶段带环”——我们需要把DP和高斯消元相结合,在整体层面采用动态规划框架,而在局部使用高斯消元解出互相影响的状态。我们用一道例题来具体说明这类情况。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探