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;
}
原文地址:https://www.cnblogs.com/wdt1/p/13939761.html