设为首页 加入收藏

TOP

POJ 1903 & ZOJ 2469 & UVA 1326 Jurassic Remains (部分枚举)
2014-11-23 19:38:03 来源: 作者: 【 】 浏览:21
Tags:POJ 1903 ZOJ 2469 UVA 1326 Jurassic Remains 部分 枚举

题意:给定n个只有大写字母组成的字符串,选取尽可能多的字符串,使得这些字符串中每个字母的个数都是偶数。n<=24

思路:直接枚举每个字符串的选或不选,复杂度是O(2^n)。其实还有更简便的方法。

对于每个字母,其实具体出现了多少次并不重要,重要的是奇数次还是偶数次,我们用0对应奇数次,1对应偶数次。对于每个字符串,我们就可以计算出对应的二进制数,方法如下。如果A出现奇数次,那么二进制数第一个位置为1,偶数次为0;如果B出现奇数次,那么二进制数第二个位置为1,偶数次为0……以此类推,每个位置都有一个对应的0或1。这样就组成了一个二进制数。所以我们就可以将题意转化为找到尽量多的数字,使得他们的异或和为0。

直接枚举复杂度是O(2^n),但是我们不妨枚举前n/2个数字的选或不选,将所有可以得到的异或值存在一个STL的map中(键为异或和,值为得到这个异或和的选或不选的状态集合,对于同一个键,保留选取的数字最多的情况),然后枚举后n/2个数字的选或不选,计算出每个异或和,在map中查找是否有异或和等的键(因为两个相同的数字异或值为0),更新答案。

这样的复杂度只有O(2^[n/2] * logn)。

#include
#include
#define MAXN 30
using namespace std;

int n,a[MAXN];
char s[1005];
map F;

int bitcount(int x) {return x  bitcount(x/2)+(x&1):0;} //计算一个数二进制表示后所包含的1的个数
int main()
{
	while(~scanf("%d",&n))
	{
		for(int i=0;i>j)&1)*a[j];//计算每种状态的异或和
			if(F.count(x) || bitcount(i)>bitcount(F[x])) F[x]=i;//F记录每个异或值所对应的字符串选取状态
		}
		int ans=0;//答案记录最终的选取状态
		for(int i=0;i < (1<< n2);++i)  //枚举后n/2个数的每种状态
		{
			int x=0;
			for(int j=0;j>j)&1)*a[j+n1];//计算每种状态的异或和
			if(F.count(x) && bitcount(i)+bitcount(F[x])>bitcount(ans)) ans=(i<>i)&1) printf("%d ",i+1);
		printf("\n");
	}
	return 0;
}

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇[HDU 1548]A Strange Lift[Dijkst.. 下一篇POJ 1159 Palindrome (动态规划)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C语言中,“指针”用 (2025-12-26 15:20:18)
·在c语言的指针运算中 (2025-12-26 15:20:15)
·C语言-函数指针与函 (2025-12-26 15:20:12)
·求navicat for mysql (2025-12-26 13:21:33)
·有哪位大哥推荐一下m (2025-12-26 13:21:30)