【插头DP】 HYSBZ 1187 神奇游乐园
通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1187
题意:单回路,权值,可选可不选,权值和最大。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 const int MAX_N = 107; 8 const int MAX_M = 7; 9 const int HASH = 1007; 10 const int MAX_S = 1000007; 11 12 struct node { 13 int head[HASH], nxt[MAX_S], dp[MAX_S], st[MAX_S]; 14 int cnt; 15 void cr() { 16 memset(head, -1, sizeof head); 17 cnt = 0; 18 } 19 void push(int s, int v) { 20 int now = s % HASH; 21 for(int i = head[now]; ~i; i = nxt[i]) { 22 int p = st[i]; 23 if(p == s) { 24 dp[i] = max(dp[i], v); 25 return; 26 } 27 } 28 st[cnt] = s; 29 dp[cnt] = v; 30 nxt[cnt] = head[now]; 31 head[now] = cnt++; 32 return; 33 } 34 }d[2]; 35 36 int n, m; 37 int ans = -1e9; 38 int a[MAX_N][MAX_M]; 39 40 int find_pos(int s, int p) { 41 return (s >> (p << 1)) & 3; 42 } 43 44 void tp(int &s, int p, int v) { 45 s &= (~(3 << (p << 1))); 46 s |= (v << (p << 1)); 47 } 48 49 int find_r(int s, int p) { 50 int cnt = 0; 51 for(int i = p; i <= m; ++i) { 52 if(find_pos(s, i) == 1) ++cnt; 53 else if(find_pos(s, i) == 2) --cnt; 54 if(!cnt) return i; 55 } 56 } 57 58 int find_l(int s, int p) { 59 int cnt = 0; 60 for(int i = p; i >= 0; --i) { 61 if(find_pos(s, i) == 2) ++cnt; 62 else if(find_pos(s, i) == 1) --cnt; 63 if(!cnt) return i; 64 } 65 } 66 67 void dpblock(int i, int j, int cur) { 68 for(int k = 0; k < d[cur].cnt; ++k) { 69 int t = d[cur].st[k]; 70 int l = find_pos(t, j - 1), r = find_pos(t, j); 71 if(l && r) { 72 if(l == 1 && r == 1) { 73 int tpos = find_r(t, j); 74 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1); 75 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 76 } else if(l == 2 && r == 1) { 77 tp(t, j - 1, 0); tp(t, j, 0); 78 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 79 } else if(l == 2 && r == 2) { 80 int tpos = find_l(t, j - 1); 81 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2); 82 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 83 } else { // 最后一个非障碍格子 84 tp(t, j - 1, 0); tp(t, j, 0); 85 if(!t) ans = max(ans, d[cur].dp[k] + a[i][j]); 86 } 87 } else if(l) { 88 if(i < n) { 89 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 90 } 91 if(j < m) { 92 tp(t, j - 1, 0); tp(t, j, l); 93 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 94 } 95 } else if(r) { 96 if(j < m) { 97 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 98 } 99 if(i < n) { 100 tp(t, j - 1, r); tp(t, j, 0); 101 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); 102 } 103 } else { // 新建 104 d[cur ^ 1].push(t, d[cur].dp[k]); //不选 105 if(i < n && j < m) { 106 tp(t, j - 1, 1); tp(t, j, 2); 107 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j]); //选 108 } 109 } 110 } 111 } 112 113 int main() { 114 scanf("%d%d", &n, &m); 115 for(int i = 1; i <= n; i ++) { 116 for(int j = 1; j <= m; j ++) { 117 scanf("%d", &a[i][j]); 118 } 119 } 120 int cur = 0; 121 d[cur].cr(); 122 d[cur].push(0, 0); 123 for(int i = 1; i <= n; i ++) { 124 for(int j = 1; j <= m; j ++) { 125 d[cur ^ 1].cr(); 126 dpblock(i, j, cur); 127 cur ^= 1; 128 } 129 for(int k = 0; k < d[cur].cnt; k ++) { 130 d[cur].st[k] <<= 2; 131 } 132 } 133 printf("%d\n", ans); 134 return 0; 135 }