https://www.luogu.org/problem/show?pid=1136
玄学dp
首先我们发现这道题有些奇怪的性质
交换k次,其实意味着k个j变成z,k个z变成j。
而且每个字最多交换一次;
但是一次交换,有可能对答案的贡献+1
也有可能+2;
这个怎么办呢?
f[i][j][k]
表示前i个里面,’j’变成’z’ j次
‘z’变成’j’ k次;
通过s[i]和s[i-1]更新
当i==k的时候更新答案;
然后预处理要小心
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int f[505][105][105];
int n,m,ans;
char c[505];
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",c+1);
memset(f,-63,sizeof f);
f[0][0][0]=f[1][0][0]=0;
if(c[1]=='j')f[1][1][0]=0;else f[1][0][1]=0;
for(int i=2;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k<=m;k++){
if(c[i-1]=='j'&&c[i]=='z')f[i][j][k]=f[i-2][j][k]+1;
if(c[i-1]=='j'&&c[i]=='j'&&j)f[i][j][k]=f[i-2][j-1][k]+1;
if(c[i-1]=='z'&&c[i]=='z'&&k)f[i][j][k]=f[i-2][j][k-1]+1;
if(c[i-1]=='z'&&c[i]=='j'&&j&&k)f[i][j][k]=f[i-2][j-1][k-1]+1;
f[i][j][k]=max(f[i][j][k],f[i-1][j][k]);
if(k==j)ans=max(ans,f[i][j][k]);
}
printf("%d",ans);
}