[HDOJ 4876] ZCC loves cards [搜索]

69 篇文章 0 订阅
17 篇文章 0 订阅

有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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值