UVA 1326 Jurassic Remains

3 篇文章 0 订阅

题目意思就是给出一堆字符串求出一个字符串集合,满足里面的每个字符的出现次数都是偶数,并且字符串的数量最多.

一看到题目首先想到的就是枚举2^24个状态,结果不用试都肯定是超时的.

然后看了解题报告,刘汝佳神牛的书上用的是二进制枚举子集加二进制存储状态来做的.

首先保存每个字符串的xor结果(同一个字符串里面的字符也是可以配对的).

然后首先枚举前n / 2个字符串子集,将各个子集的字符串xor值用map存起来.

然后再枚举后n - n / 2个字符串的子集,判断各个子集的xor值是否存在map中(也就是偶数,配对上了),维护字符串数量最多的子集.

总的复杂就是2^(n/2) * logn

#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
const int maxn = 25;

map<int,int>tb;
int A[maxn];
char s[1000];
int n;

int bitcount(int x){
	int ret = 0;
	while(x){
		if(x & 1)ret++;
		x >>= 1;
	}
	return ret;
} 
int main(){
	while(~scanf("%d", &n)){
		tb.clear();
		for(int i = 0; i < n; ++i){
			scanf("%s", s);
			A[i] = 0;
			for(int j = 0; s[j]; ++j){
				A[i] ^= (1 << (s[j] - 'A'));
			}
		}
		int n1 = n / 2, n2 = n - n1, ans = 0;
		for(int i = 0; i < (1 << n1); ++i){//枚举前n / 2个字符串的xor值所对应的子集
			int x = 0;//子集对应的xor值
		 	for(int j = 0; j < n1; ++j){
	 			if(i & (1 << j)){//子集中有这个字符串 
			 		x ^= A[j];//xor
			 	} 
	 		}
	 		if(!tb.count(x) || bitcount(tb[x]) < bitcount(i)){//x尚不存在对应的子集或者当前枚举的子集中的字符串数量比x对应的子集的字符串多 
		 		tb[x] = i;//更新xor值对应的子集 
		 	}
		}
		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];//xor
			 	} 
	 		}
	 		if(tb.count(x) && bitcount(ans) < bitcount((i << n1) ^ tb[x])){//当前子集的值存在于前n / 2个子集中(配对上了) 
		 		ans = (i << n1) ^ tb[x];//更新最大子集(i << n1 因为是后半部分)
		 	}
		}
		printf("%d\n", bitcount(ans));
		for(int i = 0; i < n; ++i){
			if(ans & (1 << i)){//最大子集中存在这个字符串  
				printf("%d ", i + 1);
			}
		}
		printf("\n");
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值