[luoguP1136]迎接仪式
显然一次操作应该是将一个j和一个z调换才优。
我们考虑将一次操作直接看作将一个j变成z,并将一个z变成j。
应为操作次数k<=100,不难想到将状态设计为:f[i][j]表示当前已经将多少个j变成z,多少个z变成j。
统计答案再记一维0/1表示当前字符。滚动数组即可
- 代码
#include<bits/stdc++.h>
using namespace std;
int f[2][101][101][2];
// j-z z-j j/z
char x[520];
int n,k;
int main()
{
scanf("%d%d",&n,&k);
memset(f,-9999,sizeof(f));
scanf("%s",x+1);
if(x[1]=='j')f[0][0][0][0]=0,f[0][1][0][1]=0;
else f[0][0][1][0]=0,f[0][0][0][1]=0;
int nw=0,pst=1;
for(int id=2;id<=n;id++){
swap(nw,pst);
for(int i=0;i<=k;i++)for(int j=0;j<=k;j++)f[nw][i][j][0]=f[nw][i][j][1]=-9999;
if(x[id]=='j'){
for(int i=0;i<=k;i++)
for(int j=0;j<=k;j++){
f[nw][i][j][0]=max(f[nw][i][j][0],f[pst][i][j][0]);
f[nw][i][j][0]=max(f[nw][i][j][0],f[pst][i][j][1]);
if(i)f[nw][i][j][1]=max(f[nw][i][j][1],f[pst][i-1][j][1]);
if(i)f[nw][i][j][1]=max(f[nw][i][j][1],f[pst][i-1][j][0]+1);
}
}
if(x[id]=='z'){
for(int i=0;i<=k;i++)
for(int j=0;j<=k;j++){
if(j)f[nw][i][j][0]=max(f[nw][i][j][0],f[pst][i][j-1][0]);
if(j)f[nw][i][j][0]=max(f[nw][i][j][0],f[pst][i][j-1][1]);
f[nw][i][j][1]=max(f[nw][i][j][1],f[pst][i][j][1]);
f[nw][i][j][1]=max(f[nw][i][j][1],f[pst][i][j][0]+1);
}
}
}
int ans=0;
for(int i=0;i<=k;i++){
ans=max(ans,f[nw][i][i][0]);
ans=max(ans,f[nw][i][i][1]);
}
printf("%d\n",ans);
}