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 }
View Code

 

posted @ 2020-03-25 18:54  古比  阅读(158)  评论(0)    收藏  举报