状态DP,设S为当前已经获得的武器的集合,预处理全部S能攻击的集合g[S]。
后面的状态转移就是
dp[st]=sum{dp[st^(1<<i)] | i为st的元素,且i为个g[st^(1<<i)]的元素}
ll dp[1<<16]; int g[1<<16]; int n; int p[20]; int read() { char s[20][20]; scanf("%d",&n); for(int i=0;i<=n;i++) scanf("%s",s[i]); for(int i=0;i<=n;i++) { p[i]=0; for(int j=0;j<n;j++) if(s[i][j]=='1')p[i]|=(1<<j); } int total=(1<<n)-1; for(int st=0;st<=total;st++) { g[st]=p[0]; for(int i=1;i<=n;i++) { int j=i-1; if(st&(1<<j))g[st]|=p[i]; } } return 0; } int main() { int t; scanf("%d",&t); for(int ca=1;ca<=t;ca++) { read(); memset(dp,0,sizeof(dp)); dp[0]=1; int total=(1<<n)-1; for(int st=1;st<=total;st++) { for(int i=0;i<n;i++)if(st&(1<<i)) { if(g[st^(1<<i)]&(1<<i)) dp[st]+=dp[st^(1<<i)]; } } printf("Case %d: %lld ",ca,dp[total]); } return 0; }