Hdu 6017 Girls Love 233【Dp+思维】好题~

Girls Love 233

 
 Accepts: 30
 
 Submissions: 218
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
除了翘课以外,结识新的妹子也是呃喵重要的日程安排之一。
这不,呃喵又混进了一个叫做ACgirls的女生群里,来达成自己不可描述的目的。
然而,呃喵只会喵了个咪地说话,于是很容易引起注意。为了掩饰自己的真实身份,呃喵每次说话都小心翼翼。
她知道,很多女生都喜欢说"233",然而呃喵想说的话一开始就确定好了,所以她要对这句话做修改。
这句话的长度为n,语句里的字符不是'2'就是'3'。
呃喵的智力非常有限,只有m点。她每次操作可以交换两个相邻的字符,然而代价是智力-2。
现在问你,在使得自己智力不降为负数的条件下,呃喵最多能使这个字符串中有多少个子串"233"呢?
如"2333"中有一个"233","232323"中没有"233"
输入描述
第一行为一个整数T,代表数据组数。
接下来,对于每组数据——
第一行两个整数n和m,分别表示呃喵说的字符串长度 以及呃喵的智力
第二行一个字符串s,代表呃喵具体所说的话。

数据保证——
1 <= T <= 1000
对于99%的数据,1 <= n <= 10, 0 <= m <= 20
对于100%的数据,1 <= n <= 100, 0 <= m <= 100
输出描述
对于每组数据,输出一行。
该行有1个整数,表示最多可使得该字符串中有多少个"233"
输入样例
3
6 2
233323
6 1
233323
7 4
2223333
输出样例
2
1
2

思路(脑洞蛮大的一个题):


1、设定dp【i】【j】【k】表示还有i个2没有处理,最后一个2现在处于位子j,并且组成了k个233的最小智力花费。

那么此时我们可以有:

dp【i-1】【t】【k+(位子t和位子j相差距离是否比2大)】=min(【i-1】【t】【k+(位子t和位子j相差距离是否比2大)】,dp【i】【j】【k】+abs(pos【i-1第i-1个2的位子】-t));

那么过程维护,我们枚举dp【i】【j】【k】<=m的进行状态转移即可。

问题难点在于设定维度上边,如果dp数组设定出来了,状态转移不是很难转移。


2、注意这里T很大,并且小数据很多,所以我们不能直接memset.


Ac代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[150][150][150];
int pos[150];
char a[1000];
int n,m;
void init()
{
    for(int i=0;i<=5+n;i++)
    {
        for(int j=0;j<=5+n;j++)
        {
            for(int k=0;k<=5+n;k++)
            {
                dp[i][j][k]=0x3f3f3f3f;
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init();
        m/=2;
        scanf("%s",a+1);
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(a[i]=='2')pos[++cnt]=i;
        }

        pos[++cnt]=n+1;
        dp[cnt][n+1][0]=0;
        for(int i=cnt;i>=1;i--)
        {
            for(int j=0;j<=n+1;j++)
            {
                for(int k=0;k<=n/3+2;k++)
                {
                    if(dp[i][j][k]<=m)
                    {
                        for(int t=j-1;t>=1;t--)
                        dp[i-1][t][k+(t+2<j)]=min(dp[i-1][t][k+(t+2<j)],dp[i][j][k]+abs(pos[i-1]-t));
                    }
                }
            }
        }
        int ans=0;
        for(int j=0;j<=n+1;j++)
        {
            for(int k=0;k<=n/3+2;k++)
            {
                if(dp[1][j][k]<=m)
                ans=max(k,ans);
            }
        }
        printf("%d\n",ans);
    }
}

















评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值