题目意思还是有点绕的,想了好一会

大体上是一个状压dp(废话

 f[j] ,当当前拥有武器集合为j 时,消灭所有怪物的方案数

像线性dp一样,但可以去掉一维

 f[j]+=f[t] ,t= j^(1<<i ) 条件是 武器库j 能消灭 怪物i 

这就要处理出 g[j] ,表示 武器库 j 能消灭的怪物集合 

 

#include<iostream>
#include<string>
#include <cstring>
#include <algorithm>
using namespace std;

 const int N=17;
 unsigned long long f[1<<N];
 int a[N],n,g[1<<N];
 
 main(){
    //freopen("in","r",stdin);
     int i,j,cas,T=0;
     cin>>cas;
     
     while(cas--){
     cin>>n;
     memset(f,0,sizeof f);
     for(i=0;i<n+1;i++){
         char c; a[i]=0;
         for(j=0;j<n;j++){
             cin>>c; if(c=='1') a[i]|=(1<<j);
         }
     }
     g[0]=a[0];
    for(i=1;i<(1<<n);i++){
        g[i]=a[0];
        for(j=0;j<n;j++)
         if(i&(1<<j)) g[i]|=a[j+1];
    }
    f[0]=1;
    for(i=0;i<(1<<n);i++)
     for(j=0;j<n;j++){
         int t=i^(1<<j);
         if(g[t]&(1<<j)) f[i]+=f[t];
     }
     printf("Case %d: %lld\n",++T,f[(1<<n)-1]);
    }
 }
 
 
 

 

posted on 2022-10-28 16:13  towboat  阅读(12)  评论(0)    收藏  举报