洛谷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; }
没有人不辛苦,只有人不喊疼