您的位置:首页 > 大数据 > 人工智能

UVALive 2965-Jurassic Remains (Mitm)中途相遇法+bitmask

2016-03-30 16:51 543 查看
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34853

题目大意:给出N个字符串,字符串里面的字符全是大写字母,要求你在N个字符串中选出M个字符串,使这M个字符串的每个字符出现的个数为偶数,求M的最大值

把字符串压缩到一个int的26位。要求一个字符串子集中 所有字符出现个数为偶数,也就是所以字符串的异或值为0

n=24,直接枚举子集的2^N 略大。。

我们可以先枚举n/2个字符串的子集,并把值映射到map/hash,

然后再枚举后n-n/2个字符串的子集,枚举过程中,对一个值X,如果能在map里找到则更新答案,否则跳过

复杂度就从2^n降到了 2^(n/2)* logn  。。。(logn是map的)

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;

const double pi=acos(-1.0);
double eps=0.000001; /*
__int64 min(__int64 a,__int64 b)
{return a<b?a:b;}
__int64 max(__int64 a,__int64 b)
{return a>b?a:b;}*/

char tm[28][28];
int A[28];
int B[28];
int bit[28];
map<int,int>sb,ans;
int main()
{
int n;
int i,j;
for (i=0;i<26;i++)
bit[i]=1<<i;

while(scanf("%d",&n)!=EOF)
{
sb.clear();
ans.clear();
for (i=0;i<n;i++)
{
A[i]=0;
scanf("%s",tm[i]);
int len =strlen(tm[i]);
for (j=0;j<len;j++)
A[i]^=bit[ tm[i][j]-'A' ];
}
int n1=n/2;
int n2=n-n1;

int all=1<<n1;
sb[0]=0;
ans[0]=0;
for (i=0;i<all;i++)
{
int cun=0,tmp=0;
int x=i;
for (j=0;j<n1;j++)
{
if ((x&(1<<j))==0)continue;
cun++;
tmp^=A[j];
}
if (sb.count(tmp)==0||sb[tmp]<cun)
sb[tmp]=cun,ans[tmp]=i;
}

int maxx=0;
int max_mark1=0;
int max_mark2=0;
all=1<<n2;
for (i=0;i<all;i++)
{
int cun=0,tmp=0;
int x=i;
for (j=0;j<n2;j++)
{
if ((x&(1<<j))==0)continue;
cun++;
tmp^=A[n1+j];
}
if (sb.count(tmp)==0) continue;
if (cun+sb[tmp]>maxx)
{
max_mark1=ans[tmp];
max_mark2=i;
maxx=cun+sb[tmp];
}
}
printf("%d\n",maxx);
int out[80];
int ok=0;

for (i=0;i<n1;i++)
{
if (max_mark1&(1<<i)) out[++ok]=i;
}
for (i=0;i<n2;i++)
{
if (max_mark2&(1<<i)) out[++ok]=n1+i;
}
for (i=1;i<=ok;i++)
{
if (i!=1) printf(" ");
printf("%d",out[i]+1);
}
printf("\n");
}
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: