中途相遇法就是 2^n种状态 不全部枚举 先枚举2^*(n/2)个状态 再枚举后 n/2个 2^(n/2)种转态 再与前面 2^(n/2)个相匹配这样复杂度会降很多,二分的思想
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
map<int, int> cnt, sym;
int cnt2[11000], sym2[11000];
int a[1000], n , b[1000];
char s[2000];
void dfs1(int pre,int va,int sum,int n,int la)
{
if(sum > cnt[va]){
cnt[va] = sum;
sym[va] = pre;
}
for(int i = la; i < n; i++)
if(!(pre & (1<<i))){
dfs1(pre | (1<<i), va^a[i], sum+1, n, i + 1);
}
}
void dfs2(int pre,int va,int sum,int n,int la)
{
cnt2[pre] = sum;
sym2[pre] = va;
for(int i = la; i < n; i++)
if(!(pre & (1<<i))){
dfs2(pre | (1<<i), va^b[i], sum+1, n, i + 1);
}
}
int main()
{
while(scanf("%d", &n)!=EOF)
{
cnt.clear();
memset(cnt2,0,sizeof(cnt2));
sym.clear();
memset(sym2,0,sizeof(sym2));
int n1 = n/2, n2 = n - n1;
for(int i = 0; i < n1; i++)
{
scanf("%s", s);
a[i] = 0;
for(int j = 0; s[j]; j++) a[i] ^= (1 << (s[j] - 'A'));
}
for(int i = 0; i < n2; i++)
{
scanf("%s", s);
b[i] = 0;
for(int j = 0; s[j]; j++) b[i] ^= (1 << (s[j] - 'A'));
}
dfs1(0, 0, 0, n1, 0);
dfs2(0, 0, 0, n2, 0);
int ansCnt = 0,ans = 0;
int la = (1<<n2);
for(int i = 0; i < la; i++)
{
int o = sym2[i];
int pre = cnt[o];
int oo = cnt2[i];
if(pre != 0 || o == 0 )
{
if(pre + oo > ansCnt)
{
ansCnt = pre + oo;
ans = (sym[o]|(i<<n1));
}
}
}
printf("%d\n", ansCnt);
int sum = 1;
bool sym = true;
while(ans)
{
if(ans & 1)printf("%d ",sum);
ans >>= 1;
sum++;
}
printf("\n");
}
return 0;
}