当前位置: 代码迷 >> 综合 >> Jurassic Remains LA 2965(中途相遇法)
  详细解决方案

Jurassic Remains LA 2965(中途相遇法)

热度:26   发布时间:2024-01-09 02:42:23.0

【中途相遇法】:

首先,如果将每种状态用位表示,就是2^24种状态,1表示奇数个,0表示偶数个。利用异或运算的特殊性,模二加,奇数与奇数异或是偶数。所以我们的目的是找出m个数异或,使他们的结果为0。到这里为止,已经保证了编码的简便性。

但是,复杂度任然是难以支撑。朴素的算法为2^24(==16000000)种情况,超时。书中提供“中途相遇法”,将考虑的情况分为两半,一边是2^12(==4096)种,因为两个数异或,只有完全相等,才能为0。所以生成前半部分的“选取个数”(我们只关注这个)和“异或结果”的匹配的集合map。后半部分,每次生成一个新的匹配的时候,查找用nlog2(n)的复杂度即可。精髓在于“打表+查找”?

【综合复杂度】:2* 2^24+24*log2(24)约等于10000

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<string.h>
#define mod 256
#define maxn 10005
using namespace std;int A[30];
char s[30];
map<int,int> table;
int bitcount(int x){return x==0? 0 : bitcount(x/2)+(x&1);}int main(){int n;while(cin>>n&&n){for(int i=0;i<n;i++){cin>>s;A[i]=0;for(int j=0;s[j]!='\0';j++){A[i]^=(1<<(s[j]-'A'));}}table.clear();int n1=n/2,n2=n-n1;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(!table.count(x) || bitcount(table[x])<bitcount(i)) table[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[j+n1];if(table.count(x)&&bitcount(ans)<bitcount(i)+bitcount(table[x]))ans=(i<<n1)^table[x];}printf("%d\n",bitcount(ans));for(int i=0;i<n;i++)if(ans&(1<<i))    printf("%d ",i+1);puts("");}return 0;}