1. 程式人生 > >洛谷P2704 炮兵陣地

洛谷P2704 炮兵陣地

本題過於經典......

對於這種網格狀壓DP,套路一波刷表法DFS轉移就沒了。

三進位制狀壓,0表示當前,上一個都沒有。1表示當前無,上一個有。2表示當前有。

轉移的條件就是上一行為0,當前不是山地,且左邊兩個都不是2。

注意有個坑點,全部轉移會超時。因為本題有很多廢狀態(山地),初始化-1然後判斷是否轉移即可。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 
 5 const int N = 110, M = 12;
 6 
 7 int
n, m, f[N][200010], pre[M], now[M], ans, G[N][M]; 8 char str[M]; 9 10 inline int zip(int *a) { 11 int t = 0; 12 for(int i = 0; i < m; i++) { 13 t = t * 3 + a[i]; 14 } 15 return t; 16 } 17 18 inline void unzip(int x, int *a) { 19 for(int i = m - 1; i >= 0; i--) { 20 a[i] = x % 3
; 21 x /= 3; 22 } 23 return; 24 } 25 26 void DFS(int x, int y, int lastans) { 27 if(y >= m) { 28 int s = zip(now); 29 f[x][s] = std::max(f[x][s], lastans); 30 ans = std::max(ans, lastans); 31 return; 32 } 33 DFS(x, y + 1, lastans); 34 if
(!G[x][y] && pre[y] == 0 && (y < 1 || now[y - 1] < 2) && (y < 2 || now[y - 2] < 2)) { 35 now[y] = 2; 36 DFS(x, y + 1, lastans + 1); 37 now[y] = 0; 38 } 39 return; 40 } 41 42 int main() { 43 memset(f, -1, sizeof(f)); 44 scanf("%d%d", &n, &m); 45 for(int i = 1; i <= n; i++) { 46 scanf("%s", str); 47 for(int j = 0; j < m; j++) { 48 G[i][j] = (str[j] == 'H'); 49 } 50 } 51 52 int lm = 1; 53 for(int i = 1; i <= m; i++) { 54 lm *= 3; 55 } 56 f[0][0] = 0; 57 for(int i = 0; i < n; i++) { 58 for(int s = 0; s < lm; s++) { 59 if(f[i][s] == -1) { 60 continue; 61 } 62 unzip(s, pre); 63 for(int j = 0; j < m; j++) { 64 now[j] = std::max(0, pre[j] - 1); 65 } 66 DFS(i + 1, 0, f[i][s]); 67 } 68 } 69 70 printf("%d", ans); 71 return 0; 72 }
AC程式碼

我陣列一開始開了2^m個......應該是3^m。