现在的位置: 首页 > 综合 > 正文

HDU 3006 The Number of set — 简单巧妙的位运算

2013年10月26日 ⁄ 综合 ⁄ 共 1081字 ⁄ 字号 评论关闭
/*
	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;
}


抱歉!评论已关闭.