uva1326(位运算,中途相遇)

Paleontologists in Siberia have recently found a number of fragments of Jurassic period dinosaur skeleton.
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.
Input
Input consists of several datasets. The first line of each dataset contains N — the number of bones
(1 ≤ N ≤ 24). Next N lines contain bones descriptions: each line contains a non-empty sequence of
different capital letters, representing labels marking the joints of the corresponding bone.
Output
For each dataset, on the first line of the output file print L — the maximal possible number of bones
that could be used to reassemble skeleton fragments. After that, in another line, output L integer
numbers in ascending order — the bones to be used. Bones are numbered starting from one, as they
are given in the input file.
Sample Input
1
ABC
6
ABD
EG
GE
ABE
AC
BCD
Sample Output
0
5
1 2 3 5 6

题目大意:有n个字符串,问你最多可以选择多少个字符串,让他们的和每个字母出现的次数都是偶数。

题目思路:根据题目要求,首先可以想到 ^运算符,可以先将每个字符串进行位运算,保存他的位向量,然后枚举所有可能的方案,但是有一个问题是,由于n=24,所以2的24次方有些庞大,我们可以使用中途相遇法,枚举前一半,在枚举后一半,当他们的亦或值相等时,比较大小

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;
int a[30];
char s[100];
map<int,int>Q;
int result[30];
int bitcount(int x)
{
    return x==0?0:bitcount(x/2)+(x&1);
}
int main()
{
    int n;
    while(~scanf("%d",&n)){
        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;
        int n2=n-n1;
        Q.clear();
        for(int i=0;i<(1<<n1);i++){
            int x=0;
            for(int j=0;j<n1;j++){
                if(i&(1<<j)){
                  x^=a[j];
                }
            }
            if(!Q.count(x)||bitcount(Q[x])<bitcount(i)){
                Q[x]=i;
            }
        }
        int ans=0;
        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];
                }
            }
            if(Q.count(x)&&bitcount(ans)<bitcount(Q[x])+bitcount(i)){
                ans=(i<<n1)^Q[x];  //左移n1位
            }
        }
        printf("%d\n",bitcount(ans));
        int res=0;
        for(int i=0;i<n;i++){
            if(ans&(1<<i)){
                result[res++]=i+1;
            }
        }
        for(int i=0;i<res;i++){
            printf("%d%c",result[i],i==res-1?'\n':' ');
        }
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值