P1136 迎接仪式
题意:给出一串字符串,只包含j z 这两种小写字母,可以进行k次交换,使其出现最多的jz (教主)
思路: 我们用一个dp【i】【j】【k】【1/0】 来进行状态转移
那么如何转移呢?因为是要执行交换,所以很难操作,我们就直接记录交换了几次
如:j 表示有j个j换成了z k表示有k个z换成了j 最后一维的0/1表示当前位置是j(0) z(1)
i是指前i个字符,我们逐一遍历过去,只需要记录前一位是什么字符,所以只需要(0/1)
初始化:首先将dp数组都附负无穷的值之后,再将dp【0】【0】【0】【1】=0;
接下来便是一个数一个数慢慢操作,从前i个操作到前i+1个操作到前n个
针对于前k个数,我们对这一位置要么改为j,要么改为z进行更新,
到最后的时候,只有j跟k交换的次数相等的时候才满足答案(因为j与z进行交换,所以肯定交换次数相等)

1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <climits> 5 #define N 520 6 #define K 120 7 using namespace std; 8 char s[N]; 9 int a[N]; 10 int f[N][K][K][2]; 11 int main() 12 { 13 int n,m; 14 int i,j,k; 15 cin>>n>>m>>s; 16 for(i=1;i<=n;i++) 17 a[i]=s[i-1]=='z'; 18 for(i=0;i<N;i++) 19 for(j=0;j<K;j++) 20 for(k=0;k<K;k++) 21 f[i][j][k][0]=f[i][j][k][1]=INT_MIN; 22 f[0][0][0][1]=0; 23 for(i=1;i<=n;i++) 24 for(j=0;j<=m;j++) 25 for(k=0;k<=m;k++){ 26 f[i][j][k][a[i]]=max(f[i-1][j][k][0]+a[i],f[i-1][j][k][1]); 27 if(a[i]){ 28 if(k) 29 f[i][j][k][0]=max(f[i-1][j][k-1][0],f[i-1][j][k-1][1]); 30 } 31 else{ 32 if(j) 33 f[i][j][k][1]=max(f[i-1][j-1][k][0]+1,f[i-1][j-1][k][1]); 34 } 35 } 36 for(i=k=0;i<=m;i++) 37 k=max(k, max(f[n][i][i][0],f[n][i][i][1])); 38 cout<<k<<endl; 39 return 0; 40 }