记录延续性的一类dp

一些满足最优子结构的关于连续区间的问题,可以尝试在第一维枚举数组的时候,

添加一个维度表示第i个数是否和前面连续,

例如dp[i][0]表示i未操作最优,dp[i][1]表示i正在操作最优,dp[i][2]表示i之前已经结束操作最优

----------------------------------------------------------------------------------------------------------------

例题1: Alyona and Strings

划分k段的最长公共子序列

增添一维表示i与j是否和i-1,j-1同属一段,0是1否,

只有当a[i]==b[j],才更新dp[i][j][k][0],由dp[i-1][j-1][k-1][1]和dp[i-1][j-1][k][0]转移而来

然后dp[i][j][k][1]始终保持大于等于dp[i][j][k][0],这样可以把延续性传递下去

写的不太好,还是结合代码感觉更能体会是个啥套路

link

----------------------------------------------------------------------------------------------------------------

例题2:01串,flip一段连续区间让交错子序列最长

这个就比较套路了,因为最优子结构是满足的

那么设dp[i][2][3]表示前i个数字,0/1结尾,未反转/反转中/已反转结束的最长长度

这里反是转结束不包括第i位,方便分清楚,反正最后取最大就从dp[n]那6个里面拿就行了

这样划分状态之后就能很好的通过状态之间的更新描述出flip的效果了

上一段代码体会一下更新的套路

	if(s[i]=='1'){
			dp[i][1][0]=dp[i-1][0][0]+1;
			dp[i][0][0]=dp[i-1][0][0];
			dp[i][1][1]=max(dp[i-1][1][0],dp[i-1][0][1])+1;
			dp[i][0][1]=dp[i-1][0][1];
			dp[i][1][2]=max(max(dp[i-1][0][0],dp[i-1][0][2]),dp[i-1][1][1])+1;
			dp[i][0][2]=dp[i-1][0][2];
		}

由于最优子结构,只要保证不会用翻过一次的最优去更新没翻过的最优来维护最优结构就做到约束了

原文地址:https://www.cnblogs.com/Drenight/p/8611762.html