洛谷P1136 迎接仪式 动态规划

显然,这是一道动归题。
我们发现,每次交换时只可能交换不同的字母(交换同类字母显然是没有意义的)。那么每次交换等同于将 111"j""j""j" 变为 "z""z""z",一个 zzz 变为 "j""j""j"
定义状态 dp[i][a][b]dp[i][a][b]dp[i][a][b],即考虑到第 iii 个字符,将 aaajjj 进行变换,bbb"z""z""z" 进行变换的最大价值。
对于相邻的字母,只有4种可能,也只有4种转移方程,分别为:

  1. jjjjjjdp[i][a][b]=dp[i−2][a−1][b]+1dp[i][a][b]=dp[i-2][a-1][b]+1dp[i][a][b]=dp[i2][a1][b]+1
  2. jzjzjzdp[i][a][b]=dp[i−2][a][b]+1dp[i][a][b]=dp[i-2][a][b]+1dp[i][a][b]=dp[i2][a][b]+1
  3. zjzjzjdp[i][a][b]=dp[i−2][a−1][b−1]+1dp[i][a][b]=dp[i-2][a-1][b-1]+1dp[i][a][b]=dp[i2][a1][b1]+1
  4. zzzzzzdp[i][a][b]=dp[i−2][a][b−1]+1dp[i][a][b]=dp[i-2][a][b-1]+1dp[i][a][b]=dp[i2][a][b1]+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;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/9845070.html