您的位置:首页 > 其它

uvalive 2965(状态压缩)

2015-02-12 17:57 387 查看
题意: 有n个字母组成的字符串,选尽量多的字符串,每个字母出现的都是偶数次。

题解:用状态压缩,把每个字符串出现的字母都在对应位置标记,如果出现偶数次标记为0,出现奇数次标记为1,那么最后选择的所有字符串对应位异或运算后应该是0,xor值是0的两个数要相等。然后因为每个字符串都是要或者不要,暴力要2^n,为了减少时间,用中途相遇法,先把前n / 2个字符串暴力一下,把对应子集内选中的字符串都xor一遍,更新相等xor的对应子集选中字符串数量(存到map里),然后枚举后n / 2个字符串的所有子集,在map中查找更新出最大子集。

#include <stdio.h>
#include <map>
using namespace std;
const int N = 30;
map<int, int> m;
char str[1000];
int f
;

int bitcount(int x) {
return x == 0 ? 0 : bitcount(x / 2) + (x & 1);
}

int main() {
int n;
while (scanf("%d", &n) == 1 && n) {
m.clear();
for (int i = 0; i < n; i++) {
scanf("%s", str);
f[i] = 0;
for (int j = 0; str[j] != '\0'; j++)
f[i] ^= (1 << str[j] - 'A');
}
int n1 = n / 2, n2 = n - n1;
for (int i = 0; i < (1 << n1); i++) {
int x = 0;
for (int j = 0; j < n1; j++)
if (i & (1 << j))
x ^= f[j];
if (!m.count(x) || bitcount(m[x]) < bitcount(i))
m[x] = i;
}
int res = 0;
for (int i = 0; i < (1 << n2); i++) {
int x = 0;
for (int j = 0; j < n2; j++)
if (i & (1 << j))
x ^= f[n1 + j];
if (m.count(x) && bitcount(res) < bitcount(m[x]) + bitcount(i))
res = (i << n1) ^ m[x];
}
printf("%d\n", bitcount(res));
for (int i = 0; i < n; i++)
if (res & (1 << i))
printf("%d ", i + 1);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  uva