题意:第一行数据总数
接下来输入机器人个数
再一行告诉你人能杀死哪些机器人,
再n行告诉你机器人的武器能怎么互相杀死
思路:状态压缩+dp
伪转移方程:dp【当前状态】=sum{dp[不杀死机器人i的状态]},(其中i属于[0,n])
批注比较多的代码
#include<bits/stdc++.h>
using namespace std;
int attack[17];//每个机器人能杀死的其他所有机器人
int can_attack[1<<17];//杀死第i号机器人后得到的武器可以杀死的所有其他机器人
long long dp[1<<17];
int t,n;
char s[17];
void pre()
{
for(int i=0;i<=n;i++)
{
attack[i]=0;
cin>>s;
for(int j=0;j<n;j++)
if(s[j]=='1')attack[i]|=(1<<j);//把第j位制为1,表示每个机器人能干掉的
}
int maxx=(1<<n)-1;
for(int state=0;state<=maxx;state++)//枚举状态
{
can_attack[state]=attack[0];
for(int j=1;j<=n;j++)//枚举机器人
if(state&(1<<(j-1)))//如果i状态里有j机器人
can_attack[state]|=attack[j];
}
}
void solve(int cases)
{
memset(dp,0,sizeof(dp));
dp[0]=1;
int maxx=(1<<n)-1;
for(int state=1;state<=maxx;state++)
for(int j=0;j<n;j++)
if( (state&(1<<j)) && (can_attack[state^(1<<j)]&(1<<j)))
//如果能干掉j号机器人 而且 在不能干掉j的状态里拥有的武器中,有能杀死j的武器
dp[state]+=dp[state^(1<<j)];
cout<<"Case "<<cases<<": "<<dp[maxx]<<endl;
}
int main()
{
//freopen("in.in","r",stdin);
ios::sync_with_stdio(false);cin.tie(NULL);
cin>>t;
int cnt=0;
while(t--)
{
cin>>n;
pre();
solve(++cnt);
}
}