hdu 3006 枚举集合能够产生的全部并集的集合
Posted lcchuguo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 3006 枚举集合能够产生的全部并集的集合相关的知识,希望对你有一定的参考价值。
http://acm.hdu.edu.cn/showproblem.php?
pid=3006
刚买的CHERRY键盘 手感真好 可惜不习惯 写代码老是打错。一个题写了一上午,都是各种按错键DEBUG.....
開始想的是DFS 发现好像不行
然后想的是两重循环能够枚举全部的2个集合的并集。3重循环能够枚举全部3个集合的并集,那么n个子集貌似须要n重循环。NP问题啊,,。。。
做法还是从小的数去模拟,由于仅仅有14个。所以状压存储
如第一个样例
四个子集1,2,3,4
二进制0001 0010 0011 0100
第一个与其它三个或操作 得到0001 0010 0011 0100 0011 0101....
然后第二个数和新的数异或
代码中第二重循环 i+1開始,放反复,事实上省不了多少时间 o(╯□╰)o
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> #include <queue> using namespace std; #define IN(s) freopen(s,"r",stdin) #define CL(a,b) memset(a,b,sizeof(a)) const int MAXN = 1<<15; int vis[MAXN],ans[MAXN]; int main() { //IN("hdu3006.txt"); int n,m; int k; while(~scanf("%d%d",&n,&m)) { CL(vis,0); int cnt=0; for(int j=0;j<n;j++) { scanf("%d",&k); int t=0,a=0; for(int i=0;i<k;i++) { scanf("%d",&t); a|=1<<(t-1); } if(!vis[a]) { vis[a]=1; ans[cnt++]=a; } } int ct=cnt; for(int i=0;i<ct;i++) { int s=ans[i]; for(int j=i+1;j<cnt;j++) { if(!vis[(s|ans[j])] && i!=j) { vis[s|ans[j]]=1; ans[cnt++]=s|ans[j]; } } } printf("%d\n",cnt); } return 0; }
以上是关于hdu 3006 枚举集合能够产生的全部并集的集合的主要内容,如果未能解决你的问题,请参考以下文章