您的位置:首页 > 其它

[HDOJ 4876] ZCC loves cards [搜索]

2014-07-25 13:18 483 查看
有n张牌,每个牌上都有数字,从中选取k张,排成一个环。在这k个牌组成的环中随意选取连续的几张,把上边的值取异或,可以得到一个值。要求这n张牌选k个排成的环中,某个环可以取出异或值为L~R的所有数字,现已给出L,问最大的R可以为多少。若无法组成L,则输出0。

题目数据为随机生成。

数据范围:n不超过20,k不超过6,牌上的每个数字和L和R不超过128。

搜索,加一些剪枝。

首先从n张牌中选取k张,不带先后顺序,复杂度为C(20,6)=38760。因为数据为随机生成,6个数最多只能凑出64个不同的异或值,而一共有128个值,所以可以减小一半的复杂度。

在剩下的38760/2=19380中,对牌进行排列,由于是环,所以可以减小一重排列,共生成5!种排列,复杂度19380*5!=2325600。

对于每种排列,暴力判断其能够组成的30种数字,然后从l开始查看能够组成到多少。

外加个剪枝,如果未进行排列时,随意选取这k张数据能够组成的连续数字的最大值都不超过当前结果,则不对其进行排列搜索。

总复杂度6*10^7...外加剪枝不知道剪掉多少...

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n,k,l,ans;
int a[20];
int b[20];
bool have[128];
int tmphave[128];
int tmpcs;

int check2(int c[]) {
int i;
tmpcs++;
//for (i=0;i<k;i++) printf("%d ",c[i]);
//printf("\n");
for (i=0;i<k;i++) {
int cur=c[i];
tmphave[cur]=tmpcs;
for (int j=1;j<k;j++) {
int tmp=i+j;
if (tmp>=k) tmp-=k;
cur^=c[tmp];
tmphave[cur]=tmpcs;
}
}
for (i=l;i<128&&tmphave[i]==tmpcs;i++);
//printf("%d\n",i-1);
return i-1;
}
void check() {
if (have[l]==false) return;
int i;
for (i=l;i<128&&have[i];i++);
int r=i-1;
if (r<=ans) return;
int c[20];
memcpy(c,b,sizeof(b));
sort(c,c+k);
do {
ans=max(ans,check2(c));
} while(next_permutation(c+1,c+k)&&r>ans);
}
void dfs1(int i,int used) {
bool tmp[128];
if (used==k) {
check();
return;
}
memcpy(tmp,have,sizeof(have));
for (;i+k-used<=n;i++) {
b[used]=a[i];
for (int j=0;j<128;j++) {
if (tmp[j]||tmp[j^a[i]]) have[j]=true;
else have[j]=false;
}
dfs1(i+1,used+1);
}
}

int main() {
int i;
tmpcs=1;
memset(tmphave,0,sizeof(tmphave));
while (scanf("%d%d%d",&n,&k,&l)!=EOF) {
for (i=0;i<n;i++) scanf("%d",&a[i]);
ans=0;
memset(have,0,sizeof(have));
have[0]=true;
dfs1(0,0);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: