链接:https://ac.nowcoder.com/acm/problem/21352
来源:牛客网
题目描述
给你一个偶数长度的字符串,你想要给每一个字符标记成蓝色或者红色,使得红色的字符序列等于蓝色的字符序列,一共有多少种方法可以做这件事
输入描述:
输入一行包含一个字符串s, (2 ≤ |s| ≤ 40)
字符串的每个字符为'o'或者'x'
输出描述:
输出一个整数
示例1
输入
oxox
输出
2
示例2
输入
oooxxx
输出
0
示例3
输入
xoxxox
输出
4
示例4
输入
xo
输出
0
示例5
输入
ooooxoox
输出
8
示例6
输入
ooxxoxox
输出
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; }