洛谷P1136 迎接仪式题解

    本题设计的十分巧妙,首先根据题意可以得到我们需要设计的状态是前i个转移k次的最大值,由于每个位置可以与不同的地方转化,所以我们需要开成四维空间

记录前i个,“j”转化了j次,“z“转化了k次,其中i位转化成的是什么,因为如果不记录最后一位的情况,那么会出现i位变成j,i+1位是z的情况不会被记录。

下面是代码时间:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<functional>
#include<string>
#include<algorithm>
#include<iostream>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
using namespace std;
const int N=510;
const int inf=0x3f3f3f3f;
const int K=120;
int f[N][K][K][2];//最后一位0代表变成0或1 
int a[N];
int main(){
    int n,m;
    int i,j,k;
    string s;
    cin>>n>>m;
    cin>>s;
    memset(f,-0x3f,sizeof f);
    for(i=0;i<s.size();i++){//j为0,z为1 
        if(s[i]=='z')
        a[i+1]=1;
        else
        a[i+1]=0;
    }
    f[0][0][0][1]=0;//防止当第一位是z的时候转移,所以0的位置不能设置为0,1的位置可以设置为0 
    for(i=1;i<=n;i++){
        for(j=0;j<=m&&j<=i;j++){
            for(k=0;k<=m&&k<=i;k++){
            f[i][j][k][a[i]]=max(f[i-1][j][k][0]+a[i],f[i-1][j][k][1]);//初始就是i-1的两种情况,但是当前面是0时如果当前位是1,那么可以加1 
                if(a[i]>0){
                    if(k)
                    f[i][j][k][0]=max(f[i-1][j][k-1][0],f[i-1][j][k-1][1]);//如果当前位是1,那么可以把当前位转化,那么就是1变化k-1次的两种情况 
                }
                else{
                    if(j)
                    f[i][j][k][1]=max(f[i-1][j-1][k][0]+1,f[i-1][j-1][k][1]);//如果当前位是0,那么可以转化为1,就是j-1次的两种情况,当能产生01时,+1 
                }
            }
        }
    }  
    int res=0;
    for(i=0;i<=m;i++)
    res=max(res,max(f[n][i][i][0],f[n][i][i][1]));
    cout<<res<<endl;
}
View Code
posted @ 2019-12-11 22:27  朝暮不思  阅读(198)  评论(0编辑  收藏  举报