/*
translation:
要给n头牛分配m个牛舍,每头牛有自己喜爱的若干牛舍。问总共有多少种分配方法?
solution:
状态压缩dp即可。dp[s]表示到状态s的方案数目
note:
* 注意用__builtin_popcount(s)函数来判断1的个数是否满足转移的条件。
date:
2016.12.31-----跨年题。希望17年赛季能够拿个牌子!!
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 20;
int dp[1 << maxn], n, m;
vector<int> like[maxn];
int main()
{
//freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &n, &m)){
for(int i = 0; i < 21; i++) like[i].clear();
int num, tmp;
for(int i = 0; i < n; i++){
scanf("%d", &num);
for(int j = 0; j < num; j++){
scanf("%d", &tmp);
like[i].push_back(tmp - 1);
}
}
memset(dp, 0, sizeof(dp));
dp[0] = 1; //到达状态0有1种方案
for(int i = 0; i < n; i++){
for(int s = 0; s < 1 << m; s++){
if(__builtin_popcount(s) == i){
for(int j = 0; j < like[i].size(); j++){
int k = like[i][j];
if(!(s >> k & 1)) dp[s | 1 << k] += dp[s];
}
}
}
}
int res = 0;
for(int i = 0; i < 1 << m; i++) if(__builtin_popcount(i) == n){
res += dp[i];
}
printf("%d\n", res);
}
return 0;
}
poj2441(状压dp)
最新推荐文章于 2023-11-12 19:17:08 发布