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

【插头DP】 HYSBZ 1187 神奇游乐园

时间:2015-07-10 18:51:07      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:

通道: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 }
View Code

 

【插头DP】 HYSBZ 1187 神奇游乐园

标签:

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

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