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 }