抽象为数学模型就是, 取尽可能多的互不相交的子集 , 使得每一个子集都能覆盖全集
#include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n; int P[1000],cover[1000],f[1000]; int main(){ scanf("%d", &n); for (int i = 0; i < n;i++) { int m, x; scanf("%d", &m); P[i] == 1 << i; while (m--) { scanf("%d", &x); P[i] |= (1 << x); } } for (int S = 1; S < n;S++) { cover[S] = 0; for (int i = 0; i < n; i++){ if (S&(1 << i)) cover[S] |= P[i]; } } f[0] = 0; int ALL = (1 << n) - 1; for (int S = 1; S < n;S++) { f[S] = 0; for (int S0 = S; S0;S0=(S0 - 1) & S) // 这是最关键的一部, 取子集操作 { if (cover[S0]==ALL) { f[S] = max(f[S], f[S^S0] + 1); //取出子集的补集+1与最大值比较 } } } printf("%d", f[ALL]); return 0; }