解析:dp[S][i][k]为队列中以有S中的人,且队尾是i,不满意的个数为k的方案数。
则dp[S][i][k] = sigma(dp[S^(1<<i)][j][k-e[i][]j])。(e[i][j]=1表示i将j视为敌人)
[code]:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
int n,m,q,mp[12][12];
LL dp[1<<12][12][12];
void init(){
memset(mp,0,sizeof(mp));
memset(dp,0,sizeof(dp));
}
void sol(){
int i,j,k,S,Ed,S_;
Ed = 1<<n;
for(S = 1;S < Ed;S++){
for(i = 0;i < n;i++){
if(!(S>>i&1)) continue;
S_ = S^(1<<i);
if(!S_){
dp[S][i][0] = 1;
continue;
}
for(j = 0;j < n;j++){
if(!(S_>>j&1)) continue;
dp[S][i][0] += (mp[i][j]?0:dp[S_][j][0]);
for(k = 1;k < n;k++){
dp[S][i][k] += dp[S_][j][k-mp[i][j]];
}
}
//for(k = 0;k < n;k++) printf("%d %d %d %lld\n",S,i,k,dp[S][i][k]);
}
}
}
int main(){
int i,j,cas,t;LL r,ans;
scanf("%d",&cas);
for(int T=1;T<=cas;T++){
scanf("%d%d%d",&n,&m,&q);
init();
for(i = 0;i < n;i++){
scanf("%d",&t);
while(t--){
scanf("%d",&j);j--;
mp[i][j] = 1;
}
}
printf("Case %d:\n",T);
sol();
while(q--){
scanf("%lld",&r);
r = m?min(n-1LL,r/m):(n-1);
ans = 0;
for(i = 0;i < n;i++){
for(j = 0;j <= r;j++){
ans += dp[(1<<n)-1][i][j];
//printf("%d %d %lld\n",i,j,dp[(1<<n)-1][i][j]);
}
}
printf("%lld\n",ans);
}
}
return 0;
}