/*
http://acm.hdu.edu.cn/showproblem.php?pid=3006 The Number of set
位运算,没什么好说了,能想到思路,代码就很容易了,细心点就是了。
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define CLR(c,v) memset(c,v,sizeof(c))
const int inf = -(1<<30);
const int INF = (1<<30);
const int M = 2e4 + 10;
template <typename _T>
_T Max(_T a, _T b){
return (a>b)?(a):(b);
}
template <typename _T>
_T Max(_T a, _T b,_T c){
return (a>Max(b,c))?(a):(Max(b,c));
}
int ans;
int set[110];
void solve(int goal_set,int h){
int tmp_goal = goal_set;
for(int i = 0 ; i < h ; i++){
if(((~goal_set) & set[i]) == 0){ // set[i] 是不是goal_set的子集
tmp_goal &= goal_set - set[i];// 是子集则去重
}
}
if(tmp_goal == 0)ans++; // 是否goal_set集合中的全部元素都能由子集合中的元素构成
}
int main(){
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int h,n; // h个小集合,n为大集合元素个数
while(cin >> h >> n){
CLR(set,0);
ans = 0;
for (int i = 0 ; i < h ; i ++){
int l;
cin >> l;
for(int j = 0 ; j < l ; j++){
int element;
cin >> element;
set[i] |= 1<<(element-1);
// 6 5 4 1 [实际输入]转换为
// 1 1 1 0 0 1 [二进制]
// 6 5 4 3 2 1 [标号|下标]
// 1表示这个选择了,0表示这个没有选择
}
}
int bound = (1<<n) - 1; // 若set.size() == n 则set的子集(不含空集)个数为(2^n)-1
for(int i = 1 ; i <= bound ; i++){
solve(i , h);
}
cout << ans << endl;
}
return 0;
}
HDU 3006 The Number of set -- 简单巧妙的位运算
最新推荐文章于 2020-07-11 09:34:43 发布