【codevs2516】【BZOJ2461】符环,DP

传送门1
传送门2
写在前面:爆〇
思路:
(下面的组合数只是快速处理出全是’S’的情况,加快程序而已= =)
刚开始有5维DP的想法(怎么总比std多一维)但显然这是错误的,即使能做也会MLE
感觉状态有点难想,f[now][x][y][z]指对位置now,左边有x个’(‘,右边有y个’)’,右边有z个’(‘(且它们都未在各自的范围内匹配),所以我们就比较容易想出它的转移了
当操作为’S’时,我们可以选’(‘,那么x+1,z+1(不要管y);
也可以选’)’,但要求x>0,不然就非法了,那么x-1,z-1或y+1(由z是否>0决定)
当操作为’D’,我们可以选’()’,那么x+1,z-1或y+1;
也可以选’)(‘,那么x-1,z+1
最后判断条件要求右边没有’(‘未匹配,并且左边’(‘与右边’)’相等,即(x==y) and (z==0)
注意:多组数据初始化,注意上述转移的条件判断

#include<bits/stdc++.h>
#define LL long long
using namespace std;
int t,len;
char s[60];
bool flag[52][52][52][52];
LL f[52][52][52][52],C[52][52];
bool pd(char ch[])
{
    for (int i=0;i<len;i++)
    if (ch[i]!='S') return 0;
    return 1;
}
LL dfs(int now,int x,int y,int z)
{
    if (now==len) return (x==y)&&(!z);
    if (flag[now][x][y][z]) return f[now][x][y][z];
    if (s[now]=='S')
    {
        f[now][x][y][z]+=dfs(now+1,x+1,y,z+1);
        if (x)
        {
            if (z) f[now][x][y][z]+=dfs(now+1,x-1,y,z-1);
            else f[now][x][y][z]+=dfs(now+1,x-1,y+1,z);
        }
    }
    else
    {
        if (z) f[now][x][y][z]+=dfs(now+1,x+1,y,z-1);
        else f[now][x][y][z]+=dfs(now+1,x+1,y+1,z);
        if (x) f[now][x][y][z]+=dfs(now+1,x-1,y,z+1);
    }
    flag[now][x][y][z]=1;
    return f[now][x][y][z];
}
main()
{
    C[0][0]=1;
    for (int i=1;i<=50;i++)
    for (int j=0;j<=i;j++)
    if (j)
    C[i][j]=C[i-1][j]+C[i-1][j-1];
    else C[i][j]=C[i-1][j];
    scanf("%d",&t);
    while (t--)
    {
        scanf("%s",s);
        len=strlen(s);
        if (pd(s)) {printf("%lld\n",(len&1)?0:C[len][len/2]/(LL)(len/2+1));continue;}
        memset(flag,0,sizeof(flag));
        memset(f,0,sizeof(f));
        printf("%lld\n",dfs(0,0,0,0));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值