状压DP UVA 11795 Mega Man's Mission

 

题目传送门

 1 /*
 2     题意:洛克人有武器可以消灭机器人,还可以从被摧毁的机器人手里得到武器,问消灭全部机器人的顺序总数
 3     状态压缩DP:看到数据只有16,就应该想到状压(并没有)。因为是照解题报告写的,代码里加点注释,省的以后忘记了
 4 */
 5 /************************************************
 6 * Author        :Running_Time
 7 * Created Time  :2015-8-8 10:41:28
 8 * File Name     :UVA_11759.cpp
 9  ************************************************/
10 
11 #include <cstdio>
12 #include <algorithm>
13 #include <iostream>
14 #include <sstream>
15 #include <cstring>
16 #include <cmath>
17 #include <string>
18 #include <vector>
19 #include <queue>
20 #include <deque>
21 #include <stack>
22 #include <list>
23 #include <map>
24 #include <set>
25 #include <bitset>
26 #include <cstdlib>
27 #include <ctime>
28 using namespace std;
29 
30 #define lson l, mid, rt << 1
31 #define rson mid + 1, r, rt << 1 | 1
32 typedef long long ll;
33 const int MAXN = 20;
34 const int INF = 0x3f3f3f3f;
35 const int MOD = 1e9 + 7;
36 ll dp[(1<<16)+10];
37 int w[MAXN];
38 int s[(1<<16)+10];
39 char mega[MAXN];
40 char robot[MAXN];
41 int n;
42 
43 int main(void)    {     //UVA 11795 Mega Man's Mission
44     int T, cas = 0;  scanf ("%d", &T);
45     while (T--) {
46         scanf ("%d", &n);
47         scanf ("%s", mega);
48 
49         memset (w, 0, sizeof (w));
50         for (int i=0; i<n; ++i)    {
51             scanf ("%s", robot);
52             for (int j=0; j<n; ++j) {
53                 if (robot[j] == '1')   {
54                     w[i] |= (1 << j);           //求出每个机器人拥有的武器,用二进制累加
55                 }
56             }
57         }
58 
59         memset (s, 0, sizeof (s));
60         for (int i=0; i<n; ++i) {
61             if (mega[i] == '1') {
62                 s[0] |= (1 << i);               //求出洛克人手里的武器
63             }
64         }
65         for (int i=1; i<(1<<n); ++i)    {       //i表示机器人死亡的情况,例如00000表示一个都没消灭,11111表示全部消灭
66             s[i] = s[0];
67             for (int j=0; j<n; ++j) {
68                 if (i & (1 << j))   {           //意思是当前第j个机器人被消灭
69                     s[i] |= w[j];               //那么能得到它的武器
70                 }
71             }
72         }
73 
74         memset (dp, 0, sizeof (dp));    dp[0] = 1;      //一个都没被消灭的方案数为1
75         for (int i=0; i<(1<<n); ++i)    {
76             if (!dp[i]) continue;
77             for (int j=0; j<n; ++j) {
78                 if ((s[i] & (1 << j)) && (i & (1 << j)) == 0)   {       //意思是当前有武器能消灭第j个机器人并且要消灭它
79                     dp[i|(1<<j)] += dp[i];                              //累加到消灭之后的状态里
80                 }
81             }
82         }
83         printf ("Case %d: %lld\n", ++cas, dp[(1<<n)-1]);        //111111全部都被消灭的方案数
84     }
85 
86     return 0;
87 }

 

posted @ 2015-08-08 13:55  Running_Time  阅读(224)  评论(0编辑  收藏  举报