例题1.25 侏罗纪 Jurassic Remains UVALive

来源:互联网 发布:vb api浏览器 user32 编辑:程序博客网 时间:2024/05/16 16:11

传送门

题目大意:给定n个大写字母组成的字符串,选定尽量多的字符串,使每个字母出现的次数均为偶数,输出选择字符串的数量以及他们的序号

解题思路:每个字母有两个状态(奇数和偶数)  因此可以进行二进制压缩(假设1表示奇数,0表示偶数),可以得到一个整数。一个字符串压缩成了一个整数。 然后每个字符串进行异或, (1 xor 1 = 0, 0 xor 0 = 0, 1 xor 0  = 1) 符合题意。直接枚举所有字符串的组合。

    这个题直接枚举时间复杂度为2 的n次方超时。可以用中途相遇法进行优化。用map映射记录前一半的情况,后一半如果出现了和之前相等的数,异或之后即为0,即题解,只需找到最多的字符串的情况就可。


AC代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <queue>#include <map>#include <stack>#include <vector>#include <string>#include <set>#include <algorithm>#include <map>#define mem(s) memset(s, 0, sizeof(s))using namespace std;int A[30];map<int, int> vist;int bitcount(int x){return x == 0? 0 : bitcount(x >> 1) + (x & 1);}int main(){int n;while(~scanf("%d", &n)){char s[1000];for(int i=0; i<n; i++){ scanf("%s", s);int len = strlen(s);A[i] = 0;for(int j=0; j<len; j++) A[i] ^= (1 << (s[j] - 'A')); }int n1 = n/2;vist.clear();for(int i=0; i< (1 << n1); i++){int x = 0;for(int j=0; j<n1; j++)if(i & (1 << j)) x ^= A[j];if(!vist.count(x) || bitcount(i) > bitcount(vist[x])) vist[x] = i; }int n2 = n-n1;int ans = 0;for(int i=0; i< (1 << n2); i++){int x = 0;for(int j=0; j<n2; j++)if(i & (1 << j)) x ^= A[n1 + j];if(vist.count(x) && bitcount(vist[x]) + bitcount(i) > bitcount(ans)) ans = (i << n1) ^ vist[x];}printf("%d\n", bitcount(ans));for(int i=0; i < 24; i++) if(ans & (1 << i)) printf("%d ", i+1);printf("\n");}return 0;}


原创粉丝点击