div题解|1392D. Omkar and Bed Wars(状态略复杂的dp)

决 策 之 间 相 互 影 响 , d p 比 较 好 解 决 这 类 问 题 决策之间相互影响,dp比较好解决这类问题 决策之间相互影响,dp比较好解决这类问题
但 是 1 和 n 是 特 殊 的 元 素 , 1 和 n 相 邻 , 考 虑 起 来 很 麻 烦 但是1和n是特殊的元素,1和n相邻,考虑起来很麻烦 但是1和n是特殊的元素,1和n相邻,考虑起来很麻烦
所 以 直 接 把 1 和 n 定 义 到 状 态 里 去 所以直接把1和n定义到状态里去 所以直接把1和n定义到状态里去
定 义 d p [ i ] [ j ] [ q ] [ k ] 为 前 i ? 1 个 人 符 合 条 件 定义dp[i][j][q][k]为前i-1个人符合条件 定义dp[i][j][q][k]为前i?1个人符合条件
且 1 号 往 j 方 向 打 人 , n 号 往 q 方 向 打 人 , 当 前 位 置 往 k 方 向 打 人 且1号往j方向打人,n号往q方向打人,当前位置往k方向打人 且1号往j方向打人,n号往q方向打人,当前位置往k方向打人
但这么设计状态是有问题的,有后效性
我们知道一个位置不合法当且仅当前面,自己,后面打人的方向一致
也就是自己只被一个人打,而且自己没有打他,这是不合法的
而对于当前状态,根本没记录被几个人打
后一个人转移的时候无法判断前一个位置是否合法
正确的状态还要加一维自己被打的信息
d p [ i ] [ j ] [ q ] [ k ] [ w ] 定 义 前 i ? 1 个 位 置 合 法 dp[i][j][q][k][w]定义前i-1个位置合法 dp[i][j][q][k][w]定义前i?1个位置合法
1 号 往 j 打 , n 号 往 q 打 , 自 己 往 k 打 , w 表 示 1号往j打,n号往q打,自己往k打,w表示 1号往j打,n号往q打,自己往k打,w表示是否被上一个人打
这样转移就很方便
【div题解|1392D. Omkar and Bed Wars(状态略复杂的dp)】 举 个 例 子 , d p [ 3 ] [ 0 ] [ 1 ] [ 0 ] [ 0 ] 的 含 义 是 ( 0 表 示 左 , 1 表 示 右 ) 举个例子,dp[3][0][1][0][0]的含义是(0表示左,1表示右) 举个例子,dp[3][0][1][0][0]的含义是(0表示左,1表示右)
前 2 个 位 置 合 法 , 1 号 往 左 打 , n 号 往 右 打 , 自 己 往 左 打 , 且 自 己 没 有 被 左 边 打 前2个位置合法,1号往左打,n号往右打,自己往左打,且自己没有被左边打 前2个位置合法,1号往左打,n号往右打,自己往左打,且自己没有被左边打
那 么 此 时 转 移 是 那么此时转移是 那么此时转移是
d p [ 3 ] [ 0 ] [ 1 ] [ 0 ] [ 0 ] = d p [ 2 ] [ 0 ] [ 1 ] [ 0 ] [ 1 ] dp[3][0][1][0][0]=dp[2][0][1][0][1] dp[3][0][1][0][0]=dp[2][0][1][0][1]
由 于 3 号 没 被 2 号 打 , 那 么 2 号 一 定 是 往 左 打 由于3号没被2号打,那么2号一定是往左打 由于3号没被2号打,那么2号一定是往左打
且 二 号 一 定 被 左 边 的 人 打 且二号一定被左边的人打 且二号一定被左边的人打
如 果 不 被 左 边 的 人 打 , 就 出 现 矛 盾 . 因 为 此 时 2 号 只 被 3 号 打 却 没 有 打 3 号 如果不被左边的人打,就出现矛盾.因为此时2号只被3号打却没有打3号 如果不被左边的人打,就出现矛盾.因为此时2号只被3号打却没有打3号
当然还有一些初始化细节,看代码吧,不懂可以评论区提问8
(如果你有更好的写法,也可以和我分享一下…)

#include using namespace std; const int maxn=2e5+10; int n,t,dp[maxn][2][2][2][2]; char a[maxn],b[maxn]; int main() { cin >> t; while( t-- ) { cin >> n; cin >> (a+1); //dp[i][j][q][k][s] 前i满足且1,n分别往j,q方向打人,s表示是否被左边打 for(int i=1; i<=n; i++) for(int j=0; j<=1; j++) for(int q=0; q<=1; q++) for(int k=0; k<=1; k++) for(int w=0; w<=1; w++) dp[i][j][q][k][w]=1e9; //下面是初始化 dp[1][0][0][0][0]=( a[1]!='L' )+( a[n]!='L'); dp[1][0][1][0][1]=( a[1]!='L' )+( a[n]!='R'); dp[1][1][0][1][0]=( a[1]!='R' )+( a[n]!='L'); dp[1][1][1][1][1]=( a[1]!='R' )+( a[n]!='R'); for(int i=2; i

    推荐阅读