kill[S]表示消灭机器人的集合为S,剩下的所能杀死的机器人集合。
设d(S)表示杀死机器人集合为S的方法数,答案为d((1<<n) - 1)。
d(S)可以由d(S')转移过来,其中S'为S中少一个机器人的子集,而且S'的状态下能够杀死缺少的这个机器人。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 16; 8 const int maxs = (1 << 16); 9 10 int n; 11 12 int kill[maxs + 10], p[maxn + 10]; 13 long long d[maxs + 10]; 14 15 char s[maxn + 10]; 16 17 int main() 18 { 19 int T; scanf("%d", &T); 20 for(int kase = 1; kase <= T; kase++) 21 { 22 scanf("%d", &n); 23 for(int i = 0; i <= n; i++) 24 { 25 p[i] = 0; 26 scanf("%s", s); 27 for(int j = 0; j < n; j++) if(s[j] == '1') p[i] |= (1 << j); 28 } 29 int all = (1 << n) - 1; 30 for(int i = 0; i <= all; i++) 31 { 32 kill[i] = p[0]; 33 for(int j = 0; j < n; j++) if(i & (1 << j)) 34 kill[i] |= p[j+1]; 35 } 36 37 memset(d, 0, sizeof(d)); 38 d[0] = 1; 39 for(int S = 1; S <= all; S++) 40 { 41 for(int i = 0; i < n; i++) if(S & (1 << i)) 42 { 43 int _S = S ^ (1 << i); 44 if(kill[_S] & (1 << i)) d[S] += d[_S]; 45 } 46 } 47 printf("Case %d: %lld ", kase, d[all]); 48 } 49 50 return 0; 51 }