标签:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4876
题意:给你N,l,k三个数,N代表N个数,从中任选k个数,然后
这k个数组成一个环,可以从这个环中选连续的1-k个数进行异或和
,把所得到的值填充到l的后面,使得有一个数r让l-r之间所有的整
整数都被这些异或和填满,求最大的r,也许表达的不太清楚,其实
就是找一个最大的r,使得给定的l到这个r之间所有的数都能够被这些
异或和表示出来,注意异或和要求是连续的数异或的和。
分析:这道题我看了好久没思路,看了大牛的博客好久没理解,脑子
比较笨知识不牢固,是这样的,这道题考察点应该是时间问题,这里
就有一个优化就是,首先就是按平常先C(n,k)进行组合,然后在
进行这k个数要进行排序牌,排序可以用next_permutation()这个
函数,我每得到一个序列就会求的一个r,最终取最大的r,优化点是
假设当前有已一个r,当取第二个组合的时候先按先按这k个数不必连续
的数进行异或和,是否可以达到当前l-r之间所有数都表示出来的效果
如果这都不是不出来我就不必再计算这组k个数的组合了,因为k<=6
所以求不必连续的异或和不会用太多时间,这里优化了时间问题就解决了
然后献上代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxk=100+10;
const int maxn=200+10;
int tmp[maxk],num[maxn],test[maxn],l,r,n,k;
bool visit[maxn];
void set(int sum,int now)
{
if(now==k+1)return;
visit[sum]=true;
set(sum^tmp[now],now+1);
set(sum,now+1);
}
bool judge()
{
memset(visit,false,sizeof(visit));
set(0,0);
for(int i=l;i<=r;i++)
if(!visit[i])
return false;
return true;
}
void control()
{
if(!judge())
return;
for(int i=0;i<k;i++)
{
test[i]=tmp[i];
}
do{
memset(visit,false,sizeof(visit));
for(int i=0;i<k;i++)
{
int sum=0;
for(int j=i;j<i+k;j++)
{
sum^=test[j%k];
visit[sum]=true;
}
for(int j=l;j<110;j++)
if(!visit[j])
{
r=max(r,j-1);
break;
}
}
}while(next_permutation(test,test+k));
}
void dfs(int con,int now)
{
if(now==k)
control();
for(int i=con;i<n;i++)
{
tmp[now]=num[i];
dfs(i+1,now+1);
}
}
int main()
{
while(~scanf("%d%d%d",&n,&k,&l))
{
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
sort(num,num+n);
r=l-1;
dfs(0,0);
if(r<l)
printf("0\n");
else
printf("%d\n",r);
}
return 0;
}
HDU 4876 ZCC loves cards【暴力+深搜+剪枝】
标签:
原文地址:http://blog.csdn.net/letterwuyu/article/details/45565511