EZOJ#584. 【2020联赛训练1】染色
原题链接:染色

输入样例:
4
cabaacba
输出样例:
4
针对样例有\(4\)种染色方案如下


算法:折半搜索
可以发现如果左半边的颜色确定了,那么右半边的串的蓝红总数就确定了.
然后在右半边暴力搜索方案即可.
可以利用\(Hash\)快速统计串.
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
const int N = 110, P = 131; //哈希时P一般取131
int n;
int col[N];
char s[N];
ULL h[N];
LL ans;
map<ULL, int> f[N / 2];
void check(int tag) {
ULL x = 0, y = 0;
int cnt = 0, cnt1 = n;
for (int i = 1; i <= n; i++) {
if (col[i] > 0) {
x += (ULL)col[i] * h[cnt];
cnt++;
}
else {
y += (ULL)col[i] * h[cnt1];
cnt1--;
}
}
if (tag == 1)
ans += f[cnt][x + y];
else
f[cnt1][x + y]++;
}
void dfs1(int x) {
if (x > n) {
check(0); //左边方案确定后,累加一下方案
return;
}
//col[i](1<=i<=n)表示1~n的染色方案,若col[i]>0,表示这个字符染成红色,若col[i]<0,表示这个字符染成蓝色
col[x] = s[x] - 'a' + 1;
dfs1(x + 1);
col[x] = -col[x];
dfs1(x + 1);
}
void dfs2(int x) {
if (x <= n) {
check(1);
return;
}
//col[i](1<=i<=n)分别表示2n~n+1的染色方案,若col[i]>0,表示这个字符染成蓝色,若col[i]<0,表示这个字符染成红色
int tmp = 2 * n - x + 1;
col[tmp] = s[x] - 'a' + 1;
dfs2(x - 1);
col[tmp] = -col[tmp];
dfs2(x - 1);
}
int main() {
cin >> n;
cin >> s + 1;
h[0] = 1;
for (int i = 1; i <= n; i++) //预处理Hash每个位上的相应权值
h[i] = h[i - 1] * P;
dfs1(1);
dfs2(2 * n);
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号