题意:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5c35f295f95ed9ad911e6a6b63b17d46.png)
解法:
二进制枚举前面一半串的染色情况,显然后面一半的涂色会受到前面的影响,
考虑固定前面一半,后面一半如何染色才满足条件:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/93984b714dab056bfc1b0cd691fb8303.png)
将相应颜色取出,发现后面一半红色的串倒着读就是前面一半蓝色的串正着读.
后面一半蓝色的串倒着读就是前面一半红色的串正着读.
后面一半可以dp计算方案数:
令d[i][j]表示后i个字符,其中j个字符是蓝色的方案数.
O(n^2)dp即可.
算法总复杂度O((2^n)*(n^2)).
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxm=2e6+5;
int d[44][44];
char s[44];
int n;
int cal(int x){
string r,b;
for(int j=0;j<n;j++){
if(x>>j&1)r+=s[j];
else b+=s[j];
}
swap(r,b);
memset(d,0,sizeof d);
d[0][0]=1;
int len1=r.size(),len2=b.size();
for(int i=0;i<n;i++){
for(int j=0;j<=i&&j<=len1;j++){
int nt=(n*2-1)-i;
if(j+1<=len1){
if(s[nt]==r[j]){
d[i+1][j+1]+=d[i][j];
}
}
if((i-j)+1<=len2){
if(s[nt]==b[i-j]){
d[i+1][j]+=d[i][j];
}
}
}
}
return d[n][len1];
}
void solve(){
cin>>n;
cin>>s;
int ans=0;
for(int i=0;i<(1<<n);i++){
ans+=cal(i);
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
solve();
return 0;
}