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' 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 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;}
- UVALive - 2965 Jurassic Remains (折半枚举法)
- 【UVALive】2965 Jurassic Remains 中途相遇法
- UVALive - 2965 Jurassic Remains 状态压缩+中途相遇法
- UVALive 2965-Jurassic Remains (Mitm)中途相遇法+bitmask
- LA --- 2965 Jurassic Remains 数相同的大写字母 【思维 + 状态压缩枚举 + 中途相遇法(折半搜索)】
- Jurassic Remains(LA 2965)位运算+枚举
- UVa1326--Jurassic Remains(折半搜索)
- LA 2965 - Jurassic Remains 中途相遇法
- LA 2965 Jurassic Remains / 中途相遇法
- LA 2965 Jurassic Remains 中途相遇法 .
- 2965 - Jurassic Remains
- POJ 1903 - Jurassic Remains 中途相遇法(枚举)
- 例题1.25 侏罗纪 Jurassic Remains UVALive
- Jurassic Remains
- Jurassic Remains
- Jurassic Remains,NEERC 2003,中途相遇法
- uva 1326 Jurassic Remains(中途相遇法)
- Uva 1326 - Jurassic Remains 中途相遇法
- 实习第一周之javaSE复习
- 2016年中总结
- NSString到底是用copy还是strong?
- 深入理解Yii2.0 (3)行为(Behavior)
- HDU 3911 Black And White(线段树区间合并+lazy操作)
- UVALive - 2965 Jurassic Remains (折半枚举法)
- 用minicom 和开发版进行通讯时 端口被锁 Device /dev/ttyS0 lock failed 解决
- RabbitMQ (三) 发布/订阅
- 写好Java代码的30条经验总结
- 8月份实习总结
- RabbitMQ (四) 路由选择 (Routing)
- 写程序很难之logstash之file input插件实现分析
- Android Studio之GsonFormat用法
- RabbitMQ (五)主题(Topic)