UVALive - 2965 Jurassic Remains (折半枚举法)

来源:互联网 发布:thanmelin 知乎 编辑:程序博客网 时间:2024/06/05 23:02

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 t 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' toZ’ 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 nd 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 rst 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 rst line of the output le 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 le.
SampleInput
1
ABC
6
ABD
EG
GE
ABE
AC
BCD
SampleOutput
0
5
1 2 3 5 6

题解:
题目不是说18s吗?O(n*2^n)应该不会超时把,可是就是超时了,谁知道为什么?
好像n=24的数据组数太多了,艹!
不过我们使用一下折半枚举就可以了,我们只需要分别枚举(n/2)的情况,然后把第一种枚举的情况存下来,然后在另外n/2的枚举来查找第一种枚举的情况就行了,在大白书上叫中途相遇法。
折半之后就直接19ms水过了。

#include<bits/stdc++.h>using namespace std;char a[27];int A[25];bool used[25];struct note {    int sel,val,nums;    bool operator<(const struct note aa)const {        return val<aa.val;    }} vec[5000];int G[5000];int main() {    #ifdef tangge    freopen("LA2965.in","r",stdin);    #endif // tangge    int n,len;    while(~scanf("%d",&n)) {        for(int i=0; i<n; ++i) {            scanf("%s",a);            len=strlen(a);            A[i]=0;            for(int j=0; j<len; ++j) {                A[i]|=(1<<(a[j]-'A'));            }        }        int all=(1<<n),nmid=n>>1,sum=1<<nmid,Max=0,selMax=0;        for(int i=0; i<sum; ++i) {            int t=0,tl=0,sel=0;            for(int j=0; j<nmid; ++j) {                if((i>>j)&1) {                    t^=A[j],++tl,sel|=(1<<j);                }            }            if(!t){                if(tl>Max)Max=tl,selMax=sel;            }            vec[i].sel=sel,vec[i].val=t,vec[i].nums=tl;        }        sort(vec,vec+sum);        int nowsum=1;        for(int i=1;i<sum;++i){            if(vec[i].val^vec[nowsum-1].val){                vec[nowsum++]=vec[i];            }else{                if(vec[i].nums>vec[nowsum-1].nums){                    vec[nowsum-1]=vec[i];                }            }        }        for(int i=0; i<nowsum; ++i)            G[i]=vec[i].val;        int newsum=1<<(n-nmid);        for(int i=0; i<newsum; ++i) {            int t=0,tl=0,sel=0;            for(int j=0; j<n-nmid; ++j) {                if((i>>j)&1) {                    t^=A[j+nmid],++tl,sel|=(1<<(j+nmid));                }            }            int pos=lower_bound(G,G+nowsum,t)-G;            if(pos<sum&&G[pos]==t){                if(Max<tl+vec[pos].nums)                    Max=tl+vec[pos].nums,selMax=vec[pos].sel|sel;            }        }        printf("%d\n",Max);        if(Max) {            int i;            for(i=0; i<n; ++i) {                if((selMax>>i)&1) {                    printf("%d",i+1);                    break;                }            }            for(++i; i<n; ++i) {                if((selMax>>i)&1) {                    printf(" %d",i+1);                }            }        }        printf("\n");    }    return 0;}
0 0
原创粉丝点击