【插头DP】HDU 1964 Pipes

通道:http://acm.hdu.edu.cn/showproblem.php?pid=1964

题意:单回路,权值,无阻碍。

代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 
  5 using namespace std;
  6 
  7 const int MAX_N = 13;
  8 const int MAX_M = 13;
  9 const int HASH = 10007;
 10 const int MAX_S = 1000007; 
 11 
 12 struct pos {
 13     int right, down;
 14     pos () {
 15         
 16     }
 17     pos(int _right, int _down) {
 18         right = _right;
 19         down = _down;
 20     }
 21 }b[MAX_N][MAX_M];
 22 
 23 struct node {
 24     int head[HASH], nxt[MAX_S];
 25     long long dp[MAX_S], st[MAX_S];
 26     int cnt;
 27     void init() {
 28         memset(head, -1, sizeof head);
 29         cnt = 0;
 30     }
 31     void push(long long s, long long v) {
 32         int now = s % HASH; 
 33         for(int i = head[now]; ~i; i = nxt[i]) if(st[i] == s) {
 34                dp[i] = min(dp[i], v);
 35             return ;
 36         }
 37         st[cnt] = s; dp[cnt] = v;
 38         nxt[cnt] = head[now];
 39         head[now] = cnt++;
 40     }
 41 }d[2];
 42 
 43 int n, m;
 44 int ex, ey;
 45 long long ans;
 46 
 47 int find_pos(long long s, int p) {
 48     return (s >> (p << 1)) & 3;
 49 }
 50 
 51 void tp(long long &s, int p, long long v) {
 52     s &= (~(3ll << (p << 1)));
 53     s |= (v << (p << 1));
 54 }
 55 
 56 int find_r(long long s, int p) {
 57     int cnt = 0;
 58     for(int i = p; i <= m; ++i) {
 59         if(find_pos(s, i) == 1) ++cnt;
 60         else if(find_pos(s, i) == 2) --cnt;
 61         if(!cnt) return i;
 62     }
 63 }
 64 
 65 int find_l(long long s, int p) {
 66     int cnt = 0;
 67     for(int i = p; i >= 0; --i) {
 68         if(find_pos(s, i) == 2) ++cnt;
 69         else if(find_pos(s, i) == 1) --cnt;
 70         if(!cnt) return i;
 71     }
 72 }
 73 
 74 void blank(int i, int j, int cur) {
 75     for(int k = 0; k < d[cur].cnt; ++k) {
 76         long long t = d[cur].st[k];
 77         int l = find_pos(t, j - 1), r = find_pos(t, j);
 78         if(l && r) {
 79             if(l == 1 && r == 1) {
 80                 int tpos = find_r(t, j);
 81                 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1);
 82                 d[cur ^ 1].push(t, d[cur].dp[k]);
 83             } else if(l == 2 && r == 1) {
 84                 tp(t, j - 1, 0); tp(t, j, 0);
 85                 d[cur ^ 1].push(t, d[cur].dp[k]);
 86             } else if(l == 2 && r == 2) {
 87                 int tpos = find_l(t, j - 1);
 88                 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2);
 89                 d[cur ^ 1].push(t, d[cur].dp[k]);
 90             } else { // 最后一个非障碍格子 
 91                 tp(t, j - 1, 0); tp(t, j, 0);
 92                 if (!t) if (i == ex && j == ey) ans = min(ans, d[cur].dp[k]); 
 93             }
 94         } else if(l) {
 95             if(i < n) {
 96                 d[cur ^ 1].push(t, d[cur].dp[k] + b[i][j].down);
 97             }
 98             if(j < m) {
 99                 tp(t, j - 1, 0); tp(t, j, l);
100                 d[cur ^ 1].push(t, d[cur].dp[k] + b[i][j].right);
101             }
102         } else if(r) {
103             if(j < m) {
104                 d[cur ^ 1].push(t, d[cur].dp[k] + b[i][j].right);
105             }
106             if(i < n) {
107                 tp(t, j - 1, r); tp(t, j, 0);
108                 d[cur ^ 1].push(t, d[cur].dp[k] + b[i][j].down);
109             }
110         } else { // 新建 
111             if(i < n && j < m) {
112                 tp(t, j - 1, 1); tp(t, j, 2);
113                 d[cur ^ 1].push(t, d[cur].dp[k] + b[i][j].down + b[i][j].right);
114             }
115         }
116     }
117 } 
118 
119 void block(int i, int j, int cur) {
120     for (int k = 0; k < d[cur].cnt; ++k) {
121         long long t = d[cur].st[k];
122         int l = find_pos(t, j - 1), r = find_pos(t, j);
123         if (!l && !r) d[cur ^ 1].push(t, d[cur].dp[k]);
124     }
125 } 
126 
127 char str[17];
128 int a[MAX_N][MAX_M];
129 
130 int main() {
131        int T;
132        scanf("%d", &T);
133        while (T-- > 0) {
134            scanf("%d%d%*c", &n ,&m);
135            gets(str);
136            for (int i = 1; i < n; ++i) {
137                gets(str);
138             for (int j = 1; j < m; ++j)
139                 b[i][j].right = str[2 * j] - '0';
140             gets(str);
141             for (int j = 1; j <= m; ++j)
142                 b[i][j].down = str[2 * j - 1] - '0';
143            }
144         gets(str);
145         for(int j = 1; j < m; ++j)
146             b[n][j].right = str[2 * j] - '0';
147         gets(str);
148         ex = n, ey = m;
149         int cur = 0;
150         d[cur].init();
151         d[cur].push(0, 0);
152         ans = (int)1e9;
153         for (int i = 1; i <= n; ++i) {
154             for (int j = 1; j <= m; ++j) {
155                 d[cur ^ 1].init();
156                 blank(i, j, cur);
157                 cur ^= 1;
158             }
159             for (int j = 0; j < d[cur].cnt; ++j)
160                 d[cur].st[j] <<= 2;
161         }
162         printf("%d\n", ans);
163        }
164     return 0;
165 }
166 
167 /*
168 2
169 2 2
170 #####
171 # 1 #
172 #2#3#
173 # 4 #
174 #####
175 */
View Code

 

posted @ 2015-07-10 17:45  mithrilhan  阅读(156)  评论(0编辑  收藏  举报