LA 2965 中途相遇法
题目链接:https://vjudge.net/problem/UVALive-2965
题意:
有很多字符串(24),选出一些字符串,要求这些字符串的字母都是偶数次;
分析:
暴力2^24也很大了,中途相遇法;其原理就是一分为二,两组解组成问题的解;
考虑到,每个字符串出现的次数没什么关系,只要关于他的奇偶,那么就有二进制,1出现奇数次,0偶数次;
每一个字符串对应于一个A位向量,
在前半个表中,选择一些字符串(2^12),又得到一个位向量 x,要是表中存在,则选择 字符串个数较多者;
然后枚举下半个表,要是表Map中有对应的向量,就说么这两组解会构成一个满足题意的解,
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 24; 6 map<int,int> table; 7 8 // 二进制有多少个1 9 int bitcount(int x) { 10 if(x==0) return 0; 11 else return bitcount(x/2) + (x&1); 12 } 13 14 15 16 int main() 17 { 18 int n,A[maxn]; 19 char s[1000]; 20 21 while(scanf("%d",&n)==1&&n) { 22 23 for(int i=0;i<n;i++) { 24 scanf("%s",s); 25 A[i] = 0; 26 for(int j=0;s[j]!='\0';j++) { 27 A[i]^=(1<<(s[j]-'A')); 28 } 29 } 30 31 table.clear(); 32 int n1 = n/2,n2 = n - n1; 33 for(int i=0;i<(1<<n1);i++) { 34 int x = 0; 35 for(int j=0;j<n1;j++) { 36 if(i&(1<<j)) 37 x^=A[j]; 38 } 39 if(!table.count(x)||bitcount(table[x])<bitcount(i)) 40 table[x] = i; // 字符串集合 x 对应的哪些字符串 41 } 42 43 int ans = 0; 44 for(int i=0;i<(1<<n2);i++) { 45 int x = 0; 46 for(int j=0;j<n2;j++) 47 if(i&(1<<j)) 48 x^=A[n1+j]; 49 if(table.count(x)&&bitcount(ans)<bitcount(table[x])+bitcount(i)) 50 ans = (i<<n1)^table[x]; 51 } 52 53 printf("%d\n",bitcount(ans)); 54 for(int i=0;i<n;i++) 55 if(ans&(1<<i)) 56 printf("%d ",i+1); 57 puts(""); 58 59 } 60 61 return 0; 62 }