Jurassic Remains UVALive - 2965 侏罗纪 状压+中途相遇法

版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/qq_42835910/article/details/89884488

题目链接 

     Paleontologists in Siberia have recently found a number of fragments of Jurassic period dinosaur skele- ton. The paleontologists have decided to forward them to the paleontology museum. Unfortunately, the dinosaur was so huge, that there was no box that the fragments would fit into. Therefore it was decided to split the skeleton fragments into separate bones and forward them to the museum where they would be reassembled. To make reassembling easier, the joints where the bones were detached from each other were marked with special labels. Meanwhile, after packing the fragments, the new bones were found and it was decided to send them together with the main fragments. So the new bones were added to the package and it was sent to the museum.

      However, when the package arrived to the museum some problems have shown up. First of all, not all labels marking the joints were distinct. That is, labels with letters ‘A’ to ‘Z’ were used, and each two joints that had to be connected were marked with the same letter, but there could be several pairs of joints marked with the same letter.

     Moreover, the same type of labels was used to make some marks on the new bones added to the box. Therefore, there could be bones with marked joints that need not be connected to the other bones. The problem is slightly alleviated by the fact that each bone has at most one joint marked with some particular letter

     Your task is to help the museum workers to restore some possible dinosaur skeleton fragments. That is, you have to find such set of bones, that they can be connected to each other, so that the following conditions are true:

• If some joint is connected to the other joint, they are marked with the same label.

• For each bone from the set each joint marked with some label is connected to some other joint.

• The number of bones used is maximal possible.

Note that two bones may be connected using several joints

分析:用一个二进制表示一个字母(0表示出现奇数次,1表示偶数次);此时问题变为求尽量多的数,使他们的xor值为0.

如果直接枚举时间复杂度为O(2^n)。如果使用中途相遇法:将字符串集分为前后两个部分,map记录前一个部分的枚举量,后一个部分进行枚举匹配,时间复杂度O(2^(n/2)*logn);

#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
const int N = 25;
char s[1000]; 
int nums[N];
map<int,int> table;

int bitCount(int x){
	return x == 0 ? 0 : bitCount(x>>1) + (x&1);
}
 
int main(int argc, char** argv) {
	int n;
	while( ~scanf("%d",&n) && n){
		memset(nums, 0,sizeof(nums));
		for(int i = 0; i < n; i++){
			scanf("%s",&s);
			for(int j = 0; s[j] != '\0'; j++)
				nums[i] ^= 1 << (s[j]-'A'); //二进制相应的位数表示奇偶性 
		}
		table.clear();
		int n1 = n/2, n2 = n - n1;
		for(int i = 0, len = 1 << n1; i < len; i++){//枚举前n2个元素的子集 
			int x = 0;
			for(int j = 0; j < n1; j++)				
				if((1<<j) & i)  x ^= nums[j];
			if(!table.count(x) || bitCount(table[x]) < bitCount(i)) table[x] = i;
		}
		int ans = 0;
		for(int i = 0, len = 1 << n2; i < len; i++){//枚举后了n2个元素的子集 
			int x = 0;
			for(int j = 0; j < n2; j++)				
				if((1<<j) & i) x ^= nums[j+n1]; //从n1开始后半个子集 
			if(table.count(x) && bitCount(ans) < bitCount(table[x]) + bitCount(i)) ans = (i << n1) ^ table[x];
		}
		printf("%d\n",bitCount(ans));
		for(int i = 0; i < n; i++)
			if(ans & (1<<i)) printf("%d ",i+1);	
		printf("\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42835910/article/details/89884488