决 策 之 间 相 互 影 响 , 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表示是否被上一个人打
这样转移就很方便
举 个 例 子 , 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