码迷,mamicode.com
首页 > 其他好文 > 详细

【插头DP】ZOJ 3213

时间:2015-07-14 20:12:43      阅读:91      评论:0      收藏:0      [点我收藏+]

标签:

通道:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3396

题意:简单路径,任意起点终点,权值和最大,有阻碍点。

思路:起点终点不固定,加个单插头就好了,妈蛋,单插头问题用括号匹配法搞了很久,并不对。。。too young too naive;

代码:

技术分享
  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 */
View Code

 

 

附上括号匹配法(未AC):

技术分享
  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 */
View Code

 

【插头DP】ZOJ 3213

标签:

原文地址:http://www.cnblogs.com/Rojo/p/4646376.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!