#include<stdio.h>
#include<string.h>
#define N 1<<18
long long dp[N],st[N],w[N];
int main()
{
int i,j,k,l,m,n;
scanf("%d",&l);
for(k=1;k<=l;k++)
{
memset(w,0,sizeof(0));
memset(st,0,sizeof(0));
memset(dp,0,sizeof(dp));
scanf("%d",&n);
char str[30]="";
for(i=0;i<=n;i++)
{
scanf("%s",str);
for(j=0;j<n;j++)
{
if(str[j]==49)
w[i]|=(1<<j);
}
}
st[0]=w[0];
for(i=0;i<(1<<n);i++)//st中存杀掉状态i中为1的机器人得到的武器数,即杀掉i集合后还可以杀的机器人的集合
{
st[i]=st[0];
for(j=0;j<n;j++)
{
if((1<<j)&i)
st[i]|=w[j+1];
}
}
dp[0]=1;
for(i=1;i<(1<<n);i++)//枚举状态
{
dp[i]=0;
for(j=0;j<n;j++)//在i集合中最后杀掉j的方法数
{ // j在i中 st[i^(1<<j)]是在i中杀掉除j外所有的机器人得到武器后
// 所能杀的机器人的集合,看j到底能不能放到最后杀
// 这是把所有杀人的情况分成最后杀谁几部分枚举
// 这是加法原理,如去一个地方坐飞机有a中路线,火车有b种路线,
// 客车有c种路线,那么全部的方法就是a+b+c
if( (i&(1<<j)) && ( st[i^(1<<j)] & (1<<j) ) )
{
dp[i]+=dp[i^(1<<j)];
}
}
}
printf("Case %d: %lld\n",k,dp[(1<<n)-1]);
}
return 0;
}
uva 11795 洛克人打机器人 加法原理
最新推荐文章于 2019-09-21 20:30:14 发布