poj 1185 炮兵阵地(三维状态压缩dP)

题目:http://poj.org/problem?id=1185

思路:

d[i][j][k]表示第i行的状态为第k个状态,第i-1行的状态为第j个状态的时候 的炮的数量。

1表示放大炮, 地形状态中1表示山地。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 using namespace std;
 7 #define max(a, b) (a) > (b)?(a):(b)
 8 
 9 int cnt, c[80], m, n;
10 char map[110][20], num[110];
11 int d[110][70][70], cur[110];
12 bool ok(int x)  //判断一行中,是否合法
13 {
14     if(x&(x<<1)) return false;
15     if(x&(x<<2)) return false;
16     return true;
17 }
18 void init()  //初始计算这n个 有多少种合法的状态
19 {
20     int i;
21     cnt = 0;
22     for(i = 0; i < (1<<n); i++)
23         if(ok(i))
24             c[++cnt] = i;
25 }
26 bool fit(int x, int k) //判断当前行的状态是否与 地形合法
27 {
28     if(cur[k]&x) return false;
29     return true;
30 }
31 int cal(int x)
32 {
33     int sum = 0;
34     while(x)
35     {
36         sum++;
37         x = (x&(x-1)); //计算一行中1的个数,相当于每次都减去1个1
38     }
39     return sum;
40 }
41 int main()
42 {
43     int i, j, k, t, ans;
44     while(~scanf("%d%d", &m, &n))
45     {
46         if(n==0 && m==0)
47             break;
48         init();
49         for(i = 1; i <= m; i++)
50             scanf("%s", map[i]);
51         for(i = 1; i <= m; i++)
52         {
53               cur[i] = 0;
54             for(j = 0; j < n; j++)
55             {
56                 if(map[i][j]=='H')
57                 cur[i] += 1;
58                 if(j != n-1)
59                 cur[i] = (cur[i]<<1);
60             }
61         }
62         memset(d, -1, sizeof(d));
63 
64         for(i = 1; i <= cnt; i++)  //初始第1行
65         {
66             num[i] = cal(c[i]);
67             if(fit(c[i], 1))
68             d[1][1][i] = num[i];
69         }
70         for(i = 2; i <= m; i++)
71         for(t = 1; t <= cnt; t++)
72         {
73             if(!fit(c[t], i))
74             continue;
75             for(j = 1; j <= cnt; j++)
76             {
77                 if(c[t]&c[j]) continue; //判断与上上行合法
78                 for(k = 1; k <= cnt; k++)
79                 {
80                     if(c[t]&c[k]) continue; //判断与上行合法
81                     if(d[i-1][j][k]==-1) continue;
82                     d[i][k][t] = max(d[i][k][t], d[i-1][j][k]+num[t]);
83                 }
84             }
85         }
86 
87         ans = 0;
88         for(i = 1; i <= m; i++)
89         for(j = 1; j <= cnt; j++)
90         for(k = 1; k <= cnt; k++)
91         ans = max(ans, d[i][j][k]);
92         printf("%d\n", ans);
93     }
94     return 0;
95 }

 

 

posted @ 2014-03-07 21:14  水门  阅读(169)  评论(0编辑  收藏  举报