[luoguP1136]迎接仪式

[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);
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/83001708