整理:区间DP
关于区间DP的整理
1.何为区间DP?
区间类动态规划是线性动态规划的扩展,它在分阶段地划分问题时,与阶段中元素出现的顺序和由前一阶段的哪些元素合并而来有很大的关系。
2.区间DP的状态设计与状态转移方程
区间DP的状态设计一般比较固定, \(dp[i][j]\) 表示区间 \([i,j]\) 的最优解,因为状态比较固定,所以状态转移方程也可以用两个通式进行表示:
\(dp[i][j]=max(dp[i][k]+dp[k+1][j]+cost[i][j]) (i \le k < j)\),其中 \(cost[i][j]\) 表示将区间 \([i,k]\) 和区间 \([k+1,j]\) 合并的收益
或
\(dp[i][j]=min(dp[i][k]+dp[k+1][j]+cost[i][j]) (i \le k < j)\),其中 \(cost[i][j]\) 表示将区间 \([i,k]\) 和区间 \([k+1,j]\) 合并的收益
在通式不适用的情况下,区间DP的状态转移方程可以以以下两个方面得出:
1.合并两个区间
2.使用单个元素拓展区间
以 括号配对 这道题为例,说明以上的两个方面分别是什么意思
1.由条件3,若A,B均合法,则AB合法可以得出若想使区间 \([l,r]\) 合法,可以取区间内一点 \(k\) ,先使区间 \([l,k]\) 合法,再使区间 \([k+1,r]\) 合法,那么此时区间 \([l,r]\)合法
在上述条件中,我们选择了先完成一个区间,再完成另外一个区间,最后将两个区间合并,使目标区间完成
2.由条件2,若A合法,则(A)或[A]合法可以得出若想使区间 \([l,r]\) 合法,可以先使区间 \([l+1,r]\) 合法,再加一个与 \(c[l]\) 匹配的符号,区间 \([l,r]\)合法,也可以先使区间 \([l,r-1]\)合法,再加一个与 \(c[r]\) 匹配的符号,区间 \([l,r]\)合法
当然,在多数情况下,可能会同时使用合并两个区间和使用单个元素拓展区间得出正确的转移方程,如此题
在某些情况下使用单个元素拓展区间可能会变成使用区间首尾两端的两个元素进行拓展,如此题
3.区间DP的实现
区间DP一般有两种实现方式,一种为递归方式,另外一种为循环方式
对于大多数题目,递归方式比循环方式更易理解,也更易实现,但是,尽管理论时间复杂度相同,循环方式实现的区间DP通常会比递归方式实现的区间DP更快,因为递归本身会消耗一定的时间
对于递归方式,要写成记忆化搜索的方式,不然时间复杂度将极其爆炸
int dfs(int l,int r){
if(vis[l][r])return dp[l][r];
vis[l][r]=1;
if(递归出口)return dp[l][r]=出口值;
for(int i=l;i<r;i++)dp[l][r]=max(dp[l][r],dfs(l,i)+dfs(i+1,r)+cost[l][r])//使用合并两个区间进行转移
dp[l][r]=min(dp[l][r],dfs(l+1,r)+cost[l][r])//使用单个元素拓展区间进行转移
dp[l][r]=min(dp[l][r],dfs(l,r-1)+cost[l][r])//使用单个元素拓展区间进行转移
return dp[l][r];
}
对于循环方式,遍历状态时,要遵循小规模转移到大规模的原则,即从长度小的区间转移到长度大的区间
for(int len=1;len<=n;len++){//枚举长度
for(int l=1;l<=n;l++){//枚举区间起点
int r=l+len-1;//计算区间终点
if(r>n)break;
for(int k=l;k<r;k++)dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]+cost[l][r])//转移
}
}
4.区间DP的时空复杂度
大多数区间DP的时间复杂度为\(O(n^3)\),并且几乎无法进行优化,这导致区间DP的题目数据范围不可能出到很大,几乎最大只能出到\(n \le 500\)
大多数区间DP的空间复杂度为\(O(n^2)\)

浙公网安备 33010602011771号