题目大意:有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; }
时间: 2024-10-28 21:51:15