通道:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3396
题意:简单路径,任意起点终点,权值和最大,有阻碍点。
思路:起点终点不固定,加个单插头就好了,妈蛋,单插头问题用括号匹配法搞了很久,并不对。。。too young too naive;
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #define MAXD 15 4 #define HASH 30007 5 #define SIZE 1000010 6 int N, M, maze[MAXD][MAXD], code[MAXD], ch[MAXD], num, ans; 7 struct Hashmap 8 { 9 int head[HASH], next[SIZE], state[SIZE], f[SIZE], size; 10 void init() 11 { 12 memset(head, -1, sizeof(head)); 13 size = 0; 14 } 15 void push(int st, int ans) 16 { 17 int i, h = st % HASH; 18 for(i = head[h]; i != -1; i = next[i]) 19 if(st == state[i]) 20 { 21 if(ans > f[i]) 22 f[i] = ans; 23 return ; 24 } 25 state[size] = st, f[size] = ans; 26 next[size] = head[h]; 27 head[h] = size ++; 28 } 29 }hm[2]; 30 void decode(int *code, int m, int st) 31 { 32 int i; 33 num = st & 7; 34 for(i = m; i >= 0; i --) 35 { 36 st >>= 3; 37 code[i] = st & 7; 38 } 39 } 40 int encode(int *code, int m) 41 { 42 int i, cnt = 1, st = 0; 43 memset(ch, -1, sizeof(ch)); 44 ch[0] = 0; 45 for(i = 0; i <= m; i ++) 46 { 47 if(ch[code[i]] == -1) 48 ch[code[i]] = cnt ++; 49 code[i] = ch[code[i]]; 50 st <<= 3; 51 st |= code[i]; 52 } 53 st <<= 3; 54 st |= num; 55 return st; 56 } 57 void init() 58 { 59 int i, j; 60 scanf("%d%d", &N, &M); 61 ans = 0; 62 memset(maze, 0, sizeof(maze)); 63 for(i = 1; i <= N; i ++) 64 for(j = 1; j <= M; j ++) 65 { 66 scanf("%d", &maze[i][j]); 67 if(maze[i][j] > ans) 68 ans = maze[i][j]; 69 } 70 } 71 void dpblank(int i, int j, int cur) 72 { 73 int k, left, up, t; 74 for(k = 0; k < hm[cur].size; k ++) 75 { 76 decode(code, M, hm[cur].state[k]); 77 left = code[j - 1], up = code[j]; 78 if(left && up) 79 { 80 if(left != up) 81 { 82 code[j - 1] = code[j] = 0; 83 for(t = 0; t <= M; t ++) 84 if(code[t] == up) 85 code[t] = left; 86 hm[cur ^ 1].push(encode(code, j == M ? M - 1 : M), hm[cur].f[k] + maze[i][j]); 87 } 88 } 89 else if(left || up) 90 { 91 if(maze[i][j + 1]) 92 { 93 code[j - 1] = 0, code[j] = left + up; 94 hm[cur ^ 1].push(encode(code, M), hm[cur].f[k] + maze[i][j]); 95 } 96 if(maze[i + 1][j]) 97 { 98 code[j - 1] = left + up, code[j] = 0; 99 hm[cur ^ 1].push(encode(code, j == M ? M - 1 : M), hm[cur].f[k] + maze[i][j]); 100 } 101 if(num < 2) 102 { 103 ++ num, code[j - 1] = code[j] = 0; 104 hm[cur ^ 1].push(encode(code, j == M ? M - 1 : M), hm[cur].f[k] + maze[i][j]); 105 } 106 } 107 else 108 { 109 code[j - 1] = code[j] = 0; 110 hm[cur ^ 1].push(encode(code, j == M ? M - 1 : M), hm[cur].f[k]); 111 if(maze[i][j + 1] && maze[i + 1][j]) 112 { 113 code[j - 1] = code[j] = 13; 114 hm[cur ^ 1].push(encode(code, M), hm[cur].f[k] + maze[i][j]); 115 } 116 if(num < 2) 117 { 118 ++ num; 119 if(maze[i + 1][j]) 120 { 121 code[j - 1] = 13, code[j] = 0; 122 hm[cur ^ 1].push(encode(code, j == M ? M - 1 : M), hm[cur].f[k] + maze[i][j]); 123 } 124 if(maze[i][j + 1]) 125 { 126 code[j - 1] = 0, code[j] = 13; 127 hm[cur ^ 1].push(encode(code, M), hm[cur].f[k] + maze[i][j]); 128 } 129 } 130 } 131 } 132 } 133 void dpblock(int i, int j, int cur) 134 { 135 int k; 136 for(k = 0; k < hm[cur].size; k ++) 137 { 138 decode(code, M, hm[cur].state[k]); 139 code[j - 1] = code[j] = 0; 140 hm[cur ^ 1].push(encode(code, j == M ? M - 1 : M), hm[cur].f[k]); 141 } 142 } 143 void solve() 144 { 145 int i, j, cur = 0; 146 hm[cur].init(); 147 hm[cur].push(0, 0); 148 for(i = 1; i <= N; i ++) 149 for(j = 1; j <= M; j ++) 150 { 151 hm[cur ^ 1].init(); 152 if(maze[i][j]) 153 dpblank(i, j, cur); 154 else 155 dpblock(i, j, cur); 156 cur ^= 1; 157 } 158 for(i = 0; i < hm[cur].size; i ++) 159 if(hm[cur].f[i] > ans) 160 ans = hm[cur].f[i]; 161 printf("%d\n", ans); 162 } 163 int main() { 164 int t; 165 scanf("%d", &t); 166 while(t --) 167 { 168 init(); 169 solve(); 170 } 171 return 0; 172 } 173 174 /* 175 41 176 14 177 28 178 19 179 41 180 26 181 10 182 12 183 29 184 74 185 66 186 91 187 192 188 338 189 190 */ 191 192 /* 193 194 100 195 196 4 4 197 5 1 1 4 198 0 0 7 7 199 4 0 1 8 200 1 2 4 0 201 202 6 5 203 1 1 1 1 0 204 1 0 0 1 0 205 1 0 1 1 0 206 1 0 1 0 0 207 1 1 1 0 0 208 0 0 0 0 0 209 210 3 4 211 8 7 0 7 212 0 0 8 2 213 0 0 7 4 214 215 2 4 216 8 0 1 0 217 4 5 1 0 218 219 4 4 220 1 8 0 4 221 2 1 7 0 222 4 8 2 0 223 2 0 7 1 224 225 3 4 226 4 5 0 1 227 5 1 0 7 228 4 7 0 0 229 230 3 2 231 8 2 232 0 0 233 1 0 234 235 3 4 236 0 0 1 1 237 7 0 4 2 238 1 4 0 0 239 240 4 2 241 7 7 242 0 1 243 7 7 244 0 5 245 246 3 3 247 42 0 35 248 0 0 29 249 41 33 0 250 251 252 2 2 253 49 0 254 7 10 255 256 3 2 257 0 39 258 37 15 259 0 35 260 261 3 3 262 0 49 19 263 17 0 13 264 41 29 24 265 266 3 7 267 0 16 0 11 34 38 0 268 29 48 0 0 0 12 7 269 46 39 9 12 23 2 12 270 271 272 */
附上括号匹配法(未AC):
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 const int MAX_N = 15; 8 const int MAX_M = 15; 9 const int HASH = 100007; 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, num[MAX_S]; 15 void cr() { 16 memset(head, -1, sizeof head); 17 cnt = 0; 18 } 19 void push(int s, int v, int val) { 20 int now = s % HASH; 21 for(int i = head[now]; ~i; i = nxt[i]) { 22 int p = st[i]; 23 if(p == s && num[i] == val) { 24 dp[i] = max(dp[i], v); 25 return; 26 } 27 } 28 st[cnt] = s; 29 dp[cnt] = v; num[cnt] = val; 30 nxt[cnt] = head[now]; 31 head[now] = cnt++; 32 return; 33 } 34 }d[2]; 35 36 int n, m; 37 int a[MAX_N][MAX_M]; 38 39 int find_pos(int s, int p) { 40 return (s >> (p << 1)) & 3; 41 } 42 43 void tp(int &s, int p, int v) { 44 s &= (~(3 << (p << 1))); 45 s |= (v << (p << 1)); 46 } 47 48 int find_r(int s, int p) { 49 int cnt = 0; 50 for(int i = p; i <= m; ++i) { 51 if(find_pos(s, i) == 1) ++cnt; 52 else if(find_pos(s, i) == 2) --cnt; 53 if(!cnt) return i; 54 } 55 return p; 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 return p; 66 } 67 int ans; 68 void blank(int i, int j, int cur) { 69 for(int k = 0; k < d[cur].cnt; ++k) { 70 int t = d[cur].st[k]; 71 int l = find_pos(t, j - 1), r = find_pos(t, j); 72 int sum = 0; 73 for (int z = 0; z <= m; ++z) if (find_pos(t, z)) ++sum; 74 if (d[cur].num[k] + sum <= 2) ans = max(ans, d[cur].dp[k]); 75 if (d[cur].num[k] == 2 && sum == 0) continue; 76 // if (i == 4 && j == 3 && d[cur].dp[k] == 37) printf("qa %d %d %d %d %d\n", l, r, d[cur].st[k], d[cur].dp[k], d[cur].num[k]); 77 if(l && r) { 78 if(l == 1 && r == 1) { 79 int tpos = find_r(t, j); //if (i == 2 && j == 3) printf("here %d %d %d %d\n", t, tpos, find_pos(t, 3), find_pos(t, 4)); 80 tp(t, j - 1, 0); tp(t, j, 0); if (tpos != j) tp(t, tpos, 1); 81 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 82 } else if(l == 2 && r == 1) { 83 tp(t, j - 1, 0); tp(t, j, 0); 84 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 85 } else if(l == 2 && r == 2) { 86 int tpos = find_l(t, j - 1); 87 tp(t, j - 1, 0); tp(t, j, 0); if (tpos != j - 1) tp(t, tpos, 2); 88 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 89 } else { // 最后一个非障碍格子 90 91 if (j < m) { 92 tp(t, j - 1, 0), tp(t, j, 1); 93 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 94 } 95 if (i < n) { 96 t = d[cur].st[k]; 97 tp(t, j - 1, 2), tp(t, j, 0); 98 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 99 } 100 if (i == n && j == m) { 101 tp(t, j - 1, 0); tp(t, j, 0); 102 // here 103 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 104 } 105 106 } 107 } else if(l) { 108 if(i < n) { 109 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 110 } 111 if(j < m) { 112 tp(t, j - 1, 0); tp(t, j, l); 113 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 114 } 115 if (d[cur].num[k] < 2) { 116 t = d[cur].st[k]; 117 tp(t, j - 1, 0); tp(t, j, 0); 118 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k] + 1); 119 } 120 } else if(r) { 121 if(j < m) { 122 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 123 } 124 if(i < n) { 125 tp(t, j - 1, r); tp(t, j, 0); 126 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 127 } 128 if (d[cur].num[k] < 2) { 129 t = d[cur].st[k]; 130 tp(t, j - 1, 0); tp(t, j, 0); 131 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k] + 1); 132 } 133 } else { // 新建 134 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 135 if(i < n && j < m && a[i + 1][j] && a[i][j + 1]) { 136 tp(t, j - 1, 1); tp(t, j, 2); 137 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k]); 138 } 139 if (d[cur].num[k] < 2) { 140 if (i < n && a[i + 1][j]) { 141 t = d[cur].st[k]; 142 tp(t, j - 1, 1); tp(t, j, 0); 143 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k] + 1); 144 } 145 if (j < m && a[i][j + 1]) { 146 t = d[cur].st[k]; 147 tp(t, j - 1, 0); tp(t, j, 2); 148 d[cur ^ 1].push(t, d[cur].dp[k] + a[i][j], d[cur].num[k] + 1); 149 } 150 } 151 } 152 } 153 } 154 155 void block(int i, int j, int cur) { 156 for (int k = 0; k < d[cur].cnt; ++k) { 157 long long t = d[cur].st[k]; 158 int l = find_pos(t, j - 1), r = find_pos(t, j); //if (i == 3 && j == 3) printf("%d %d %d %d %d\n", l, r, d[cur].st[k], d[cur].dp[k], d[cur].num[k]); 159 if (!l && !r) d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 160 } 161 } 162 163 164 int main() { 165 int T; 166 scanf("%d", &T); 167 while (T-- > 0) { 168 scanf("%d%d", &n, &m); 169 memset(a, 0, sizeof a); 170 memset(d[0].num, 0, sizeof d[0].num); 171 memset(d[1].num, 0, sizeof d[1].num); 172 memset(d[0].dp, 0, sizeof d[0].dp); 173 memset(d[1].dp, 0, sizeof d[1].dp); 174 ans = 0; 175 for(int i = 1; i <= n; i ++) { 176 for(int j = 1; j <= m; j ++) { 177 scanf("%d", &a[i][j]); 178 ans = max(ans, a[i][j]); 179 } 180 } 181 int cur = 0; 182 d[cur].cr(); 183 d[cur].push(0, 0, 0); 184 for(int i = 1; i <= n; i ++) { 185 for(int j = 1; j <= m; j ++) { 186 d[cur ^ 1].cr(); 187 if (a[i][j]) blank(i, j, cur); 188 else block(i, j, cur); 189 cur ^= 1; 190 } 191 for(int k = 0; k < d[cur].cnt; ++k) { 192 d[cur].st[k] <<= 2; 193 } 194 } 195 //for (int i = 0; i < d[cur].cnt; ++i) printf("%d %d\n", d[cur].st[i], d[cur].dp[i]); 196 for (int i = 0; i < d[cur].cnt; ++i) //if (d[cur].num[i] == 2) 197 ans = max(ans, d[cur].dp[i]); 198 printf("%d\n", ans); 199 } 200 return 0; 201 } 202 203 /* 204 41 205 14 206 28 207 19 208 41 209 26 210 10 211 12 212 29 213 74 214 66 215 91 216 192 217 338 218 219 */ 220 221 /* 222 223 100 224 225 4 4 226 5 1 1 4 227 0 0 7 7 228 4 0 1 8 229 1 2 4 0 230 231 6 5 232 1 1 1 1 0 233 1 0 0 1 0 234 1 0 1 1 0 235 1 0 1 0 0 236 1 1 1 0 0 237 0 0 0 0 0 238 239 3 4 240 8 7 0 7 241 0 0 8 2 242 0 0 7 4 243 244 2 4 245 8 0 1 0 246 4 5 1 0 247 248 4 4 249 1 8 0 4 250 2 1 7 0 251 4 8 2 0 252 2 0 7 1 253 254 3 4 255 4 5 0 1 256 5 1 0 7 257 4 7 0 0 258 259 3 2 260 8 2 261 0 0 262 1 0 263 264 3 4 265 0 0 1 1 266 7 0 4 2 267 1 4 0 0 268 269 4 2 270 7 7 271 0 1 272 7 7 273 0 5 274 275 3 3 276 42 0 35 277 0 0 29 278 41 33 0 279 280 281 2 2 282 49 0 283 7 10 284 285 3 2 286 0 39 287 37 15 288 0 35 289 290 3 3 291 0 49 19 292 17 0 13 293 41 29 24 294 295 3 7 296 0 16 0 11 34 38 0 297 29 48 0 0 0 12 7 298 46 39 9 12 23 2 12 299 300 301 */