题目大意:
给出有几个怪兽以及初始的可以打的怪兽的二进制序列。为1的就是可以打的为0的就是不可以打的。
打死一只怪兽后你就可以用它的武器去打特定的怪兽。
问最多有几种方案。
思路:
状态压缩DP。
S[i]表示的是当死的怪兽的状态为i的时候所获得的武器可以打死哪些怪兽。
weapon[i]表示当打死怪兽i的时候所可以获得的武器。
dp[i]表示当死的怪兽的状态为i的时候最多可以有几种方案。
代码:
#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>
const int MAX = 65550;
int S[MAX];
long long dp[MAX];
int weapon[18];
char robot[18];
char initial[18];
int main() {
int T;
int n;
scanf("%d",&T);
int kase = 0;
while(T--) {
scanf("%d %s",&n,initial);
memset(S,0,sizeof(S));
memset(weapon,0,sizeof(weapon));
memset(dp,0,sizeof(dp));
for(int i = 0; i < strlen(initial); i++) {
if(initial[i] == '1')
S[0] |=(1 << i);
}
for(int i = 0; i < n; i++) {
scanf("%s",robot);
for(int j = 0; j < strlen(robot); j++)
if(robot[j] == '1')
weapon[i] |= (1 << j);
}
for(int i = 0; i < (1 << n); i++) {
S[i] = S[0];
for(int j = 0; j < n ; j++) {
if((i & (1 << j)))
S[i] |= weapon[j];
}
}
dp[0] = 1;
for(int i = 0; i < (1 << n); i++) {
if(dp[i] == 0)
continue;
for(int j = 0;j < n; j++) {
if((S[i] &(1 << j))!= 0 && (i &(1 << j)) == 0)
dp[i | (1 << j)] += dp[i];
}
}
printf("Case %d: %lld\n", ++ kase,dp[(1 << n) - 1]);
}
return 0;
}