hdu6017(DP)

Besides skipping class, it is also important to meet other girls for luras in the new term.

As you see, luras sneaked into another girl's QQgroup to meet her indescribable aim.

However, luras can only speak like a cat. To hide her real identity, luras is very careful to each of her words.

She knows that many girls love saying "233",however she has already made her own word at first, so she needs to fix it.

Her words is a string of length n,and each character of the string is either '2' or '3'.

Luras has a very limited IQ which is only m.

She could swap two adjacent characters in each operation, which makes her losing 2 IQ.

Now the question is, how many substring "233"s can she make in the string while her IQ will not be lower than 0 after her operations?

for example, there is 1 "233" in "2333", there are 2 "233"s in "2332233", and there is no "233" in "232323".
 

Input
The first line is an integer T which indicates the case number.

and as for each case,

the first line are two integers n and m,which are the length of the string and the IQ of luras correspondingly.

the second line is a string which is the words luras wants to say.

It is guaranteed that——

1 <= T <= 1000

for 99% cases, 1 <= n <= 10, 0 <= m <= 20

for 100% cases, 1 <= n <= 100, 0<= m <= 100
 

Output
As for each case, you need to output a single line.

there should be one integer in the line which represents the largest possible number of "233" of the string after her swap.
 

Sample Input
  
  
3 6 2 233323 6 1 233323 7 4 2223333
 

Sample Output
  
  
2 1 2
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;

int dp[105][105][55][3];
char s[105];
int p[105];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        m/=2;
        scanf("%s",s+1);
        int g2=0;
        for(int i=1;i<=n;i++)
            if(s[i]=='2')
            {
                p[++g2]=i;
            }
        int g3=n-g2;
        for(int i=0;i<=g2;i++)
            for(int j=0;j<=g3;j++)
                for(int k=0;k<=m;k++)
                    for(int d=0;d<3;d++)
                        dp[i][j][k][d]=-1;
        dp[0][0][0][0]=0;
         for(int i=0;i<=g2;i++)
            for(int j=0;j<=g3;j++)
                for(int k=0;k<=m;k++)
                    for(int d=0;d<3;d++)
                        if(dp[i][j][k][d]!=-1)
                        {
                            if(j<g3)
                            {
                                int cnt=dp[i][j][k][d];
                                int tt=d;
                                if(tt)
                                {
                                    if(tt==1)
                                        tt=2;
                                    else
                                    {
                                        tt=0;
                                        cnt++;
                                    }
                                }
                                dp[i][j+1][k][tt]=max(dp[i][j+1][k][tt],cnt);//k不变,是因为只需要统计换2的次数,如果换2再换3,徒劳!
                            }
                            if(i<g2)
                            {
                                int sum=k+abs(i+j+1-p[i+1]);//第i个2和第j个3的位置和就是当前位置,和后一个2的位置比较,就知道后面的2过来这个位置,至少要交换多少次
                                if(sum<=m)
                                    dp[i+1][j][sum][1]=max(dp[i+1][j][sum][1],dp[i][j][k][d]);
                            }
                        }
    int ans=0;
    for(int i=0;i<=m;i++)
        for(int j=0;j<3;j++)
        {
            ans=max(ans,dp[g2][g3][i][j]);
        }
    printf("%d\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值