hdu 4876(剪枝+暴力)

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

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

代码实现:

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

hdu 4876(剪枝+暴力),布布扣,bubuko.com

时间: 2024-08-04 02:44:19

hdu 4876(剪枝+暴力)的相关文章

HDU 4876 ZCC loves cards(暴力剪枝)

HDU 4876 ZCC loves cards 题目链接 题意:给定一些卡片,每个卡片上有数字,现在选k个卡片,绕成一个环,每次可以再这个环上连续选1 - k张卡片,得到他们的异或和的数,给定一个L,问能组成[L,R]所有数字的情况下,R的最大值是多少 思路:暴力C(20, 6),然后对于每个序列去全排后模拟计算值, 不过之前要有个剪枝,全排前,先把k个数随机取数(即不用连续),然后如果这样还满足不了,那么连续的情况肯定也满足不了,直接结束,不进入全排.这样一来由于满足不了的情况实际上是占绝大

hdu 4876 暴力剪枝

hdu 4876 终于过了, 之前写的代码虽然思路是这样的但是有好多可以优化的地方没有注意所以一直超时超时超时!,学习了一下别人的代码,虽然看上去没什么差别但实际上却可以节省很多时间,恩恩又学到了一些技巧~     ^_^ . [题意]:给定一些卡片,每个卡片上有数字,现在选k个卡片,绕成一个环,每次可以再这个环上连续选1 - k张卡片,得到他们的异或和的数,给定一个L,问能组成[L,R]所有数字的情况下,R的最大值是多少. [思路]:暴力+剪枝  枚举在m个数里选k个数的 C(m,k)种情况,

hdu 4876 ZCC loves cards(暴力)

题目链接:hdu 4876 ZCC loves cards 题目大意:给出n,k,l,表示有n张牌,每张牌有值.选取其中k张排列成圈,然后在该圈上进行游戏,每次选取m(1≤m≤k)张连续的牌,取牌上值的亦或和.要求找到一个圈,使得L~R之间的数都可以得到,输出R.如果R < L输出0. 解题思路:暴力,首先预处理出来每种选取的亦或值,然后在该基础上从可以组成L的状态中挑选一个,L+1的状态中挑取一个,知道说总的挑取出所有状态中选中的牌的个数大于K为值,然后用全排序去查找最大的R. #includ

HDU 4876 ZCC loves cards

我决定记录下这么恶心的代码.比赛的时候头晕脑胀,写得好搓,错的地方好多好多,回来调了好久.... 做法大概就是C(20,6)选出卡牌后,再k!枚举排列,再k*k得出该排列能得出什么数字. 当然,光这样做绝对会T,里面加了各种剪枝后就1650ms险过了.. 最主要的剪枝是选出k张牌后,看牌能不能组成L~ans里面各个数字,能才进行下一步.然后k!可以拆成(k-x)!*(x!)..不过这里其实大概没什么大优化吧 #include<cstdio> #include<iostream> #

hdu 4876

ZCC loves cards Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 828    Accepted Submission(s): 184 Problem Description ZCC loves playing cards. He has n magical cards and each has a number on it

HDU 4876 ZCC loves cards _(:зゝ∠)_ 随机输出保平安

GG,,,g艹 #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <vector> #include <queue> #include <math.h> using namespace std; vector<int>G[21][7];//G[i][j] 表示n=i k=j的情况下 二进

hdu 4499 Cannon(暴力)

题目链接:hdu 4499 Cannon 题目大意:给出一个n*m的棋盘,上面已经存在了k个棋子,给出棋子的位置,然后求能够在这种棋盘上放多少个炮,要求后放置上去的炮相互之间不能攻击. 解题思路:枚举行放的情况,用二进制数表示,每次放之前推断能否放下(会不会和已经存在的棋子冲突),放下后推断会不会互相攻击的炮,仅仅须要对每一个新加入的炮考虑左边以及上边就能够了. #include <cstdio> #include <cstring> #include <algorithm&

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

题目链接: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之间所有的数都能够被这些 异或和表示出来,注意异或和要求是连续的数异或的和. 分析:这道题我看了好久

HDU 4876 ZCC loves cards 暴力+剪枝

题意:n张牌,选k个排成一圈,给出L,求出最大R 使得[L,R]内任意一个数 都可以由圈内连续m个数异或得到.n<=20,k<=6,a[i],L<=100. m为自己设定的. 暴力 总共有A(20,6)种方案 每种方案k^2算出异或数 TLE..先C(20,6)选出方案 若能过最优性剪支,在全排列更新答案. 注意先将a排序 使得全排列从最小序开始. #include <bits/stdc++.h> using namespace std; typedef long long