【u122】迎接仪式

Time Limit: 1 second
Memory Limit: 128 MB

【问题描述】
LHX教主要来X市指导OI学习工作了。为了迎接教主,在一条道路旁,一群Orz教主er穿着文化衫站在道路两旁迎接教主,每件文化衫上都印着大
字。一旁的Orzer依次摆出“欢迎欢迎欢迎欢迎……”的大字,但是领队突然发现,另一旁穿着“教”和“主”字文化衫的Orzer却不太和谐
。 为了简单描述这个不和谐的队列,我们用“j”替代“教”,“z”替代“主”。而一个“j”与“z”组成的序列则可以描述当前的队列。为了让
教主看得尽量舒服,你必须调整队列,使得“jz”子串尽量多。每次调整你可以交换任意位置上的两个人,也就是序列中任意位置上的两个
字母。而因为教主马上就来了,时间仅够最多作K次调整(当然可以调整不满K次),所以这个问题交给了你。

【输入格式】

输入文件welcome.in的第1行包含2个正整数N与K,表示了序列长度与最多交换次数。 第2行包含了一个长度为N的字符串,字符串仅由字母“j”与字母“z”组成,描述了这个序列。

【输出格式】

输出文件welcome.out仅包括一个非负整数,为调整最多K次后最后最多能出现多少个“jz”子串。
【数据规模】

对于10%的数据,有N≤10; 对于30%的数据,有K≤10; 对于40%的数据,有N≤50; 对于100%的数据,有N≤500,K≤100。

Sample Input1

5 2
zzzjj

Sample Output1

2

【样例说明】

第1次交换位置1上的z和位置4上的j,变为jzzzj;
第2次交换位置4上的z和位置5上的j,变为jzzjz。
最后的串有2个“jz”子串。

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=u122

【题解】

把j和z转换成0和1;
则原问题等价于,在字符串里面进行小于k次操作;
使得字符串中子串”01”的个数达到最大;
j和z的交换可以看成是把1变成0和0变成1的过程;
设f[i][x][y]表示前i个字符里面经过了x次0变成1,y次1变成0的过程所得到的最大”01”子串个数;
可以枚举i-1,i这两个位置的字符要不要变成01子串,即s[i-1]变成0,s[i]变成1;
这样问题就转换成前i-2个字符的问题了;
至于f[i-2][][]中的2、3维是什么状态,就根据i-1和i的情况来确定:
因为枚举了所有的i-1和i是01子串的情况。所以能够考虑到所有情况;
最后在f[n][i][i]中找答案就可以了;表示0和1的转换次数一样->相当于交换;
其次往前转移的时候,f[i-2][][]的这个状态必须要存在才行;不然会造成错解;
比如f[3][4][4];则必须先有f[3][4][3]的状态或f[3][3][3],f[3][3][4]的状态;
不能直接从f[3][0][0]跳到f[3][4][4];

【完整代码】

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <string>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

void rel(LL &r)
{
    r = 0;
    char t = getchar();
    while (!isdigit(t) && t!='-') t = getchar();
    LL sign = 1;
    if (t == '-')sign = -1;
    while (!isdigit(t)) t = getchar();
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
    r = r*sign;
}

void rei(int &r)
{
    r = 0;
    char t = getchar();
    while (!isdigit(t)&&t!='-') t = getchar();
    int sign = 1;
    if (t == '-')sign = -1;
    while (!isdigit(t)) t = getchar();
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
    r = r*sign;
}

const int MAXN = 500+10;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);

int n,k;
char s[MAXN];
int a[MAXN];
int f[MAXN][100+10][100+10];

int main()
{
   // freopen("F:\\rush.txt","r",stdin);
    rei(n);rei(k);
    scanf("%s",s+1);
    rep1(i,1,n)
        if (s[i]=='j')
            a[i] = 0;
        else
            a[i] = 1;
    memset(f,255,sizeof(f));
    int t = min(n,k);
    f[0][0][0] = 0;
    f[1][0][0] = 0;
    if(a[1]==1)
        f[1][0][1]=0;
    if(a[1]==0)
        f[1][1][0]=0;
    rep1(i,2,n)
        rep1(x,0,min(i,k))
            rep1(y,0,min(i,k))
                {
                    f[i][x][y]=f[i-1][x][y];
                    if (a[i]==0)
                    {
                        if (a[i-1]==1)
                        {
                            if (x>0 && y>0 && f[i-2][x-1][y-1]!=-1)
                                f[i][x][y] = max(f[i][x][y],f[i-2][x-1][y-1]+1);
                        }
                        if (a[i-1]==0)
                        {
                            if (x>0 && f[i-2][x-1][y]!=-1)
                                f[i][x][y] = max(f[i][x][y],f[i-2][x-1][y]+1);
                        }
                    }
                    if (a[i]==1)
                    {
                         if (a[i-1]==0)
                        {
                            if (f[i-2][x][y]!=-1)
                                f[i][x][y] = max(f[i][x][y],f[i-2][x][y]+1);
                        }
                        if (a[i-1]==1)
                        {
                            if (y>0 && f[i-2][x][y-1]!=-1)
                                f[i][x][y] = max(f[i][x][y],f[i-2][x][y-1]+1);
                        }
                    }
                }
    int ans = 0;
    rep1(i,0,k)
        ans = max(ans,f[n][i][i]);
    printf("%d\n",ans);
    return 0;
}
posted @ 2017-10-04 18:45  AWCXV  阅读(189)  评论(0编辑  收藏  举报