luogu P1136 迎接仪式

luogu P1136 迎接仪式

本题的难点是状态设计,
n^2*m 的状态设计转移太过垄杂,emmmm反正我写不出来QAQ
参考了题解

/*相同字符不用调换,一个字符最多被调换一次否则会有等价多方案变换
dp[i][j][k]表示前i个字符,改变了j个'j'和k个'z'后的答案数
那么只考虑前两位,有四种情况(jj,jz,zj,zz)来转移。
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::max;
using std::min;
char s[555];
int dp[555][105][105];  //改变了j个j,改变了k个z 
int n,K,ans;
int main() {
    scanf("%d%d",&n,&K);
    scanf("%s",s+1);
    memset(dp,245,sizeof dp);
    dp[0][0][0]=dp[1][0][0]=0;
    for (int i=2; i<=n; ++i)
      for (int j=0; j<=K; ++j)
        for (int k=0; k<=K; ++k) {
          dp[i][j][k]=dp[i-1][j][k];
          if(s[i]=='z' && s[i-1]=='j') dp[i][j][k]=max(dp[i][j][k],dp[i-2][j][k]+1);
          if(s[i]=='z' && s[i-1]=='z' && k) dp[i][j][k]=max(dp[i][j][k],dp[i-2][j][k-1]+1);
          if(s[i]=='j' && s[i-1]=='j' && j) dp[i][j][k]=max(dp[i][j][k],dp[i-2][j-1][k]+1);
          if(s[i]=='j' && s[i-1]=='z' && j && k) dp[i][j][k]=max(dp[i][j][k],dp[i-2][j-1][k-1]+1);
          if(j == k) ans=max(ans,dp[i][j][k]);
        }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/sssy/p/8562971.html