您的位置:首页 > 其它

HDU 4876 ZCC loves cards【暴力+深搜+剪枝】

2015-05-07 19:32 381 查看
题目链接: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;

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: