首页 > 代码库 > hdu 4876(剪枝+暴力)

hdu 4876(剪枝+暴力)

题意:给定n,k,l,接下来给出n个数,让你从n个数中选取k个数围成一圈,然后从这k个数中随意选出连续的m(m>=1&&m<=k)个数进行异或后得到[l,r]区间的所有值,让你求最大的r。

分析:关键问题是需要剪枝!

2014 <wbr>Multi-University <wbr>Training <wbr>Contest <wbr>2--by <wbr>镇海中学 <wbr>解题报告

代码实现:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<string>#include<set>#include<vector>using namespace std;int n,k,L,R,a[25],b[10],id;int visited[130];string str[10] = {"1", "12", "123", "1234", "12345", "123456"};int check(){    int i,j,temp[1005],tot=0,t;    temp[tot++]=0;    for(i=0;i<k;i++)//枚举所有的组合异或值    {        t=tot;        for(j=0;j<tot;j++)            temp[t++]=b[i]^temp[j];        tot=t;    }    for(i=0;i<tot;i++)        visited[temp[i]]=id;    for(i=L;i<=R;i++)        if(visited[i]!=id)            return 0;    return 1;}void dfs(int x, int num){    int i,j;    if(num==k)    {        id++;        if(check()==0)           return ;        string per = str[k-1];                do        {            if(per[0]!=1)//这里去除了很多重复的,没加这句话500ms,加了之后100ms                break;            id++;            int temp[12];            for(i=0;i<k;i++)            {                temp[i]=b[per[i]-0-1];                temp[i+k]=temp[i];            }            for(i=0;i<k;i++)            {                int flag=0;                for(j=i;j<i+k;j++)                {                    flag=flag^temp[j];                    visited[flag]=id;                }            }            if(visited[L]!=id)                continue;            i=L+1;            while(visited[i]==id)             i++;            R=R>(i-1)?R:(i-1);                    }        while(next_permutation(per.begin(),per.end()));        return ;    }    for(i=x;i<n;i++)    {        b[num]=a[i];        dfs(i+1,num+1);    }}int main(){    int i;    while(scanf("%d%d%d",&n,&k,&L)!=EOF)    {        id=0;R=0;        memset(visited,-1,sizeof(visited));        for(i=0; i<n; i++)            scanf("%d",&a[i]);        dfs(0,0);        printf("%d\n",R);    }    return 0;}