显然,这是一道动归题。
我们发现,每次交换时只可能交换不同的字母(交换同类字母显然是没有意义的)。那么每次交换等同于将
1
1
1 个
"
j
"
"j"
"j" 变为
"
z
"
"z"
"z",一个
z
z
z 变为
"
j
"
"j"
"j"。
定义状态
d
p
[
i
]
[
a
]
[
b
]
dp[i][a][b]
dp[i][a][b],即考虑到第
i
i
i 个字符,将
a
a
a 个
j
j
j 进行变换,
b
b
b 个
"
z
"
"z"
"z" 进行变换的最大价值。
对于相邻的字母,只有4种可能,也只有4种转移方程,分别为:
- j j jj jj: d p [ i ] [ a ] [ b ] = d p [ i − 2 ] [ a − 1 ] [ b ] + 1 dp[i][a][b]=dp[i-2][a-1][b]+1 dp[i][a][b]=dp[i−2][a−1][b]+1
- j z jz jz: d p [ i ] [ a ] [ b ] = d p [ i − 2 ] [ a ] [ b ] + 1 dp[i][a][b]=dp[i-2][a][b]+1 dp[i][a][b]=dp[i−2][a][b]+1
- z j zj zj: d p [ i ] [ a ] [ b ] = d p [ i − 2 ] [ a − 1 ] [ b − 1 ] + 1 dp[i][a][b]=dp[i-2][a-1][b-1]+1 dp[i][a][b]=dp[i−2][a−1][b−1]+1
- z z zz zz: d p [ i ] [ a ] [ b ] = d p [ i − 2 ] [ a ] [ b − 1 ] + 1 dp[i][a][b]=dp[i-2][a][b-1]+1 dp[i][a][b]=dp[i−2][a][b−1]+1
Code:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=600;
int d[maxn][120][120];
char A[maxn];
int main()
{
int N,K,ans=0;
scanf("%d%d",&N,&K);
scanf("%s",A+1);
memset(d,-0x3f,sizeof(d));
d[0][0][0]=0;
d[1][0][0]=0;
if(A[1]=='z')d[1][0][1]=0;
else d[1][1][0]=0;
for(int n=2;n<=N;++n)
for(int j=0;j<=K;++j)
for(int z=0;z<=K;++z)
{
d[n][j][z]=d[n-1][j][z];
if(A[n-1]=='j'&&A[n]=='j'&&j>=1)d[n][j][z]=max(d[n][j][z],d[n-2][j-1][z]+1);
if(A[n-1]=='j'&&A[n]=='z')d[n][j][z]=max(d[n][j][z],d[n-2][j][z]+1);
if(A[n-1]=='z'&&A[n]=='z'&&z>=1)d[n][j][z]=max(d[n][j][z],d[n-2][j][z-1]+1);
if(A[n-1]=='z'&&A[n]=='j'&&z>=1&&j>=1)d[n][j][z]=max(d[n][j][z],d[n-2][j-1][z-1]+1);
if(j==z)ans=max(ans,d[n][j][z]);
}
printf("%d",ans);
return 0;
}