题目大意:有N(1<=N<=16)种怪物,每种需要拥有能消灭它的一种或几种武器才能消灭,初始时有初始武器,消灭一种怪物会获得一些武器,问消灭完全部怪物的顺序有多少种。
用d[S]表示消灭状态为S(二进制)的怪物有多少种顺序,用c[S]表示消灭完S之后的武器。d[S]通过枚举最后消灭的是哪一个怪物来递推,前提是消灭除了它之外的怪物以后拿到的所有武器能消灭它。
c[S]通过取最低位来计算,即c[S]=c[S&-S]|c[S-(S&-S)]。
#include<stdio.h>
#include<stdlib.h>
typedef long long LL;
char a[30];
int c[77000];
LL d[77000];
int main(void)
{
int i,j,u,p,n,pi,qi;
LL sump;
scanf("%d",&pi);
for(qi=1;qi<=pi;qi++)
{
scanf("%d",&n);
c[0]=0;
for(i=0;i<=n;i++)
{
scanf("%s",a+1);
u=0;
for(j=n;j>=1;j--)
{
u=u*2+a[j]-'0';
}
c[(1<<i)/2]=(u|c[0]);
}
p=(1<<n);
d[0]=1;
for(i=1;i<p;i++)
{
if((i&-i)!=i)
{
c[i]=(c[i&-i]|c[i-(i&-i)]);
}
sump=0;
for(j=1;j<=n;j++)
{
u=(1<<(j-1));
if(((i&u)!=0)&&((c[i-u]&u)!=0))
{
sump=sump+d[i-u];
}
}
d[i]=sump;
}
printf("Case %d: %lld\n",qi,d[p-1]);
}
return 0;
}