红蓝字符串 牛客网

链接: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;
}

  

posted @ 2019-09-21 23:17  风雨兼程-zhi  阅读(243)  评论(0编辑  收藏  举报