首页 > 代码库 > hdu 4876(剪枝+暴力)
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;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。