uva11795

题目大意:
给出有几个怪兽以及初始的可以打的怪兽的二进制序列。为1的就是可以打的为0的就是不可以打的。
打死一只怪兽后你就可以用它的武器去打特定的怪兽。
问最多有几种方案。

思路:
状态压缩DP。
S[i]表示的是当死的怪兽的状态为i的时候所获得的武器可以打死哪些怪兽。
weapon[i]表示当打死怪兽i的时候所可以获得的武器。
dp[i]表示当死的怪兽的状态为i的时候最多可以有几种方案。

代码:

#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>
const int MAX = 65550;

int S[MAX];
long long dp[MAX];
int weapon[18];
char robot[18];
char initial[18];

int main() {

    int T;
    int n;
    scanf("%d",&T);
    int kase = 0;
    while(T--) {
        scanf("%d %s",&n,initial);
        memset(S,0,sizeof(S));
        memset(weapon,0,sizeof(weapon));
        memset(dp,0,sizeof(dp));

        for(int i = 0; i < strlen(initial); i++) {
            if(initial[i] == '1') 
                S[0] |=(1 << i);
        }
        for(int i = 0; i < n; i++) {
            scanf("%s",robot);
            for(int j = 0; j < strlen(robot); j++)
                if(robot[j] == '1')
                    weapon[i] |= (1 << j);
        }
        for(int i = 0; i < (1 << n); i++) {
            S[i] = S[0];
            for(int j = 0; j < n ; j++) {
                if((i & (1 << j)))
                    S[i] |= weapon[j];
            }
        }
        dp[0] = 1; 
        for(int i = 0; i < (1 << n); i++) {
            if(dp[i] == 0)
                continue;
            for(int j = 0;j < n; j++) {
                if((S[i] &(1 << j))!= 0 && (i &(1 << j)) == 0)
                    dp[i | (1 << j)] += dp[i];
            }
        }
        printf("Case %d: %lld\n", ++ kase,dp[(1 << n) - 1]);
    }
    return 0;
}

你可能感兴趣的:(uva11795)