传送门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));
}
}