大意:
主角自己有一些武器,然后每个机器人身上有一些武器,每个机器人需要用特定的武器才能消灭。
问,有多少种消灭机器人的顺序。
思路:
用 dp[S][i] 表示现在消灭的机器人集合为S(获得的武器也隐含在其中了,不用再开一维),而且是通过消灭第i号机器人到这个状态,这个状态下的顺序总数。
我的代码用了一个atk[S][j] 数组,表示在消灭了S这个集合机器人的情况下,能不能消灭第j个机器人,这样方便一些。
#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<vector>
#define LL long long int
using namespace std;
LL dp[1<<17][17];
int atk[1<<17][17];//?????????????????????????i????
char grid[17][17];
int n;
void process()
{
memset(atk,0,sizeof(atk));
for(int i=0;i<n;i++)
{
atk[0][i]=grid[0][i]-'0';
}
for(int i=1;i<(1<<n);i++)
{
for(int j=0;j<n;j++)
{
if( ((i)&(1<<j))==0 ) continue;
int subset=i-(1<<j);
for(int k=0;k<n;k++)
{
atk[i][k]|=atk[subset][k];
}
for(int k=0;k<n;k++)
{
atk[i][k]|=grid[j+1][k]-'0';
}
}
}
}
void solve()
{
//?????????
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
dp[1<<i][i]=grid[0][i]-'0';
}
for(int i=1;i<(1<<n);i++)
{
for(int j=0;j<n;j++)
{
if( ((i)&(1<<j))==0 ) continue;
int subset=i-(1<<j);
if(subset==0) continue;
if(atk[subset][j]==1)
{
for(int k=0;k<n;k++)
{
dp[i][j]+=dp[subset][k];
}
}
}
}
}
int main()
{
int t;
cin>>t;
for(int CS=1;CS<=t;CS++)
{
cin>>n;
for(int i=0;i<=n;i++)
{
scanf("%s",grid[i]);
}
process();
solve();
LL ans=0;
for(int i=0;i<n;i++) ans+=dp[(1<<n)-1][i];
printf("Case %d: %lld\n",CS,ans);
//23423423423
}
return 0;
}