uva1326 Jurassic Remains

137 篇文章 0 订阅
23 篇文章 0 订阅

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.

把每个字符串状压成一个整数,问题就变成了选择尽量多的整数使他们异或和为零。
直接枚举的话O(2^n)比较大,所以可以中途相遇O(2^(n/2) * logn)。
方案同样可以状压。

#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
map<int,pair<int,int> > mp;
int n,n1,a[30];
char s[30];
int main()
{
    int i,j,l,x,cnt,ans,u;
    bool flag;
    while (scanf("%d",&n)==1)
    {
        for (i=0;i<n;i++)
        {
            scanf("%s",s+1);
            l=strlen(s+1);
            a[i]=0;
            for (j=1;j<=l;j++)
              a[i]^=1<<s[j]-'A';
        }
        n1=n/2;
        mp.clear();
        for (i=0;i<(1<<n1);i++)
        {
            x=cnt=0;
            for (j=0;j<n1;j++)
              if (i&(1<<j))
              {
                cnt++;
                x^=a[j];
              }
            if (!mp.count(x)||cnt>mp[x].second)
              mp[x]=make_pair(i,cnt);
        }
        ans=u=0;
        for (i=0;i<(1<<n-n1);i++)
        {
            x=cnt=0;
            for (j=n1;j<n;j++)
              if (i&(1<<j-n1))
              {
                cnt++;
                x^=a[j];
              }
            if (mp.count(x)&&cnt+mp[x].second>ans)
            {
                ans=cnt+mp[x].second;
                u=i<<n1|mp[x].first;
            }
        }
        printf("%d\n",ans);
        flag=0;
        for (i=0;i<n;i++)
          if (u&(1<<i))
          {
            if (flag) printf(" ");
            flag=1;
            printf("%d",i+1);
          }
        printf("\n");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值