hdu4876ZCC loves cards 暴搜+剪枝

//n(1<=n<=20)个数 , 选k个数 , 让这k(1<=k<=6)个数围成一个圈
//可以在这个圈中选长度为m(1<=m<=k)连续的点
//将其异或 得到值x
//给定一个l , 问最大的r ,使得[l,r]这个圈中的x能构成[1.r]区间的所有数
//先从n个数中选k个点 , 复杂度为c(n,k)
//然后将k全排列 求得最大值
//一个剪枝是对于已经有了一个 ans 对于已经选出来的k个数能不能
//构成[l,ans]区间的所有数 , 如果不能就不用考虑全排列
//还有就是由于是一个圈,所以只需要全排列(k-1)个数就行
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
const int maxn = 130 ;
int a[130] ;
int aa[maxn] ;
int vis[maxn] ;
int A[720][10] ;
int b[maxn] ;
int n,  k ,  l ;
int ans = 0 ;
int len_a = 0;
void dfss(int len)
{
    if(len == k)
    {
        memcpy(A[len_a] , a , sizeof(a)) ;
        len_a++ ;
        return ;
    }
    for(int i = 1;i < k;i++)
    if(!vis[i])
    {
        vis[i] = 1 ;
        a[len] = i ;
        dfss(len+1) ;
        vis[i] = 0 ;
    }
}
void check(int pos , int sum)
{
    if(pos == k)
    {
        vis[sum] = 1 ;
        return ;
    }
    check(pos+1 , sum) ;
    check(pos+1 , sum^a[pos]) ;
}
void judge()
{

    memset(vis , 0 , sizeof(vis)) ;
    if(ans)
    {
        check(0 , 0) ;
        for(int i = l;i <= ans;i++)
        if(!vis[i])
        return ;
    }
    for(int i = 0;i < len_a ;i++)
    {
        memset(vis , 0 , sizeof(vis)) ;
        aa[0] = a[0] ;
        for(int j = 1;j < k;j++)
        aa[A[i][j]] = a[j] ;
        for(int j = 0;j < k;j++)
        {
            int c = 0 ;
            for(int s = 0;s < k;s++)
            {
                c ^= aa[(j+s)%k] ;
                vis[c] = 1 ;
            }
        }
        if(!vis[l])continue ;
        for(int j = l;j < maxn;j++)
        if(!vis[j])
        {
            ans = max(ans , j-1) ;
            break  ;
        }
    }
}
int dfs(int pos , int len)
{
    if(len == k)
    {
        judge() ;
        return 0;
    }
    if(pos == n)return 0 ;
    dfs(pos+1 , len) ;
    a[len] = b[pos] ;
    dfs(pos+1 , len+1) ;
    return 1 ;
}
int main()
{
   // freopen("in.txt" ,"r" , stdin) ;
    int len = 0 ;
    while(~scanf("%d%d%d" , &n , &k , &l))
    {
        len_a = 0 ;
        memset(vis , 0 , sizeof(vis)) ;
        dfss(1) ;
        for(int i = 0;i < n;i++)
        scanf("%d" , &b[i]) ;
        sort(b , b+k) ;
        ans = 0 ;
        dfs(0 , 0) ;
        printf("%d\n" , ans) ;
    }
    return  0 ;
}

你可能感兴趣的:(hdu4876ZCC loves cards 暴搜+剪枝)