b_vj_Arrange the Bulls(预处理二级制数据+暴力递推 / )
有n头牛和m个谷仓,每头牛都有自己喜爱的谷仓,而且仅喜欢独居,问有多少种分配方案能使所有牛满足自己的意愿且不冲突(不冲突是指没有两头牛或更多牛在同一个场地打篮球)
思路因为恰好要安排n头牛,所以有n个1的状态才是合法的,这一步可先预处理到数组g中;对于每一头牛的爱好\(x_i...x_{i+k}\),都去检查第x个谷仓没有被安排时的方案数,此时则表明状态为j的方案数可以从j(1<<x)从过来,所以累加上f[j(1<<x)]的方案数即可(一个终点多条路径可达嘛)
#include<iostream>
using namespace std;
int n,m,N,M,f[1<<25],g[1<<25];
void init_g() {
for (int i=0; i<M; i++)
for (int j=0; j<m; j++) if (i&(1<<j))
g[i]++;
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>n>>m, N=1<<n, M=1<<m;
init_g(), f[0]=1;
for (int i=1; i<=n; i++) {
int c; cin>>c;
while (c--) {
int x; cin>>x, x--;
for (int j=0; j<M; j++) if (j&(1<<x) && g[j]==i) {
f[j]+=f[j^(1<<x)];
}
}
}
int ans=0;
for (int i=0; i<M; i++) if (g[i]==n) {
ans+=f[i];
}
cout<<ans;
return 0;
}