链接:https://ac.nowcoder.com/acm/problem/21352
来源:牛客网
题目描述
给你一个偶数长度的字符串,你想要给每一个字符标记成蓝色或者红色,使得红色的字符序列等于蓝色的字符序列,一共有多少种方法可以做这件事
输入描述:
输入一行包含一个字符串s, (2 ≤ |s| ≤ 40)
字符串的每个字符为'o'或者'x'
输出描述:
输出一个整数
示例6
输出
复制8
先统计‘x’,‘o’,的个数l1,l2;那么最后取出的每个序列的‘x’,‘o’的个数为l1/2,l2/2。考虑涂红色,那么剩下的字符涂为蓝色,我们可以用数组来表示取得序列的状态,‘x’为1,‘o’为0.设dp【i】【j】为前i个字符中取了j个红色的字符,i-j个蓝色字符,且当前取出的两个序列的前缀相同。
那么dp【i】【j】=dp【i-1】【j-1】(第i的字符分给长度为j-1的字符)+dp【i-1】【j】(第i个字符分配个长度为i-j-1的字符)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=45;
ll dp[maxn][maxn];
char ch[maxn];
int len;
int sta[maxn];
int l1,l2;
int sta1[maxn];
ll ans=0;
ll solve(){
for(int i=0;i<=len;i++){
for(int j=0;j<=len/2;j++){
dp[i][j]=0;
}
}
dp[0][0]=1;
for(int i=1;i<=len;i++){
for(int j=1;j<=min(i,len/2);j++){
if(sta1[j-1]==sta[i-1]){
dp[i][j]+=dp[i-1][j-1];
}
if(i>j&&sta1[i-j-1]==sta[i-1]){
dp[i][j]+=dp[i-1][j];
}
}
}
return dp[len][len/2];
}
void dfs(int n){
if(l1==0&&l2==0){
ans+=solve();
return ;
}
if(l1>0){
l1--;
sta1[n]=1;
dfs(n+1);
l1++;
}
if(l2>0){
l2--;
sta1[n]=0;
dfs(n+1);
l2++;
}
}
int main(){
scanf("%s",ch);
len=strlen(ch);
for(int i=0;i<len;i++){
if(ch[i]=='o'){
sta[i]=1;
l1++;
}
else{
sta[i]=0;
l2++;
}
}
l1/=2;
l2/=2;
dfs(0);
printf("%lld\n",ans*2);
return 0;
}