【插头DP】HDU 4113 Construct the Great Wall

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

题意:简单回路,绕着格子轮廓把‘O’围起来,使得里面没有‘X’的最短路径,可选可不选。

思路:首先把格点看成方格,然后行列分别增一。对于区分‘O’和‘X’不能在同一个块里面的处理方法就是状态增加一维,表示该方框的左上角格点是否在内部。

    然后状态转移的时候都要预判一下该块的几个是否都在同一块里面,如果不在的话,就要判断左和上和当前格是否在同一个联通块里面

 

代码:

 

  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 const int mov[20] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
 13 
 14 struct node {
 15     int head[HASH], nxt[MAX_S], cnt;
 16     long long dp[MAX_S], st[MAX_S];
 17     void init() {
 18         memset(head, -1, sizeof head);
 19         cnt = 0;
 20     }
 21     void push(long long s, long long v) {
 22         int now = s % HASH; 
 23         for(int i = head[now]; ~i; i = nxt[i]) if(st[i] == s) {
 24             dp[i] = min(dp[i], v);
 25             return ;
 26         }
 27         st[cnt] = s;      dp[cnt] = v;
 28         nxt[cnt] = head[now];
 29         head[now] = cnt++;
 30     }
 31 }d[2][2];
 32 
 33 int n, m;
 34 int ex, ey, ans;
 35 char a[MAX_N][MAX_M];
 36 
 37 int find_pos(long long s, int p) {
 38     return s >> mov[p] & 3;
 39 }
 40 
 41 void tp(long long &s, int p, long long v) {
 42     s &= ~(3ll << mov[p]);
 43     s |= v << mov[p];
 44 }
 45 
 46 
 47 int find_r(long long s, int p) {
 48     int cnt = 0;
 49     for(int i = p; i <= m; ++i) {
 50         if(find_pos(s, i) == 1) ++cnt;
 51         else if(find_pos(s, i) == 2) --cnt;
 52         if(!cnt) return i;
 53     }
 54 }
 55 
 56 int find_l(long long s, int p) {
 57     int cnt = 0;
 58     for(int i = p; i >= 0; --i) {
 59         if(find_pos(s, i) == 2) ++cnt;
 60         else if(find_pos(s, i) == 1) --cnt;
 61         if(!cnt) return i;
 62     }
 63 }
 64 
 65 bool jud(int i, int j, int in) {
 66     if(a[i][j] == 'o') return in;
 67     if(a[i][j] == 'x') return !in;
 68     return true;
 69 }
 70 
 71 void blank(int i, int j, int cur, int in) {
 72     for(int k = 0; k < d[cur][in].cnt; ++k) {
 73         long long t = d[cur][in].st[k];
 74         int l = find_pos(t, j - 1), r = find_pos(t, j);
 75         if(l && r) {
 76             if(l == 1 && r == 1) {
 77                 int tpos = find_r(t, j);
 78                 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1);
 79             } else if(l == 2 && r == 1) {
 80                 tp(t, j - 1, 0); tp(t, j, 0);
 81             } else if(l == 2 && r == 2) {
 82                 int tpos = find_l(t, j - 1);
 83                 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2);
 84             } else { 
 85                 tp(t, j - 1, 0); tp(t, j, 0);
 86                 if (i == ex + 1 && j == ey + 1 && !t) 
 87                     ans = min((long long)ans, d[cur][in].dp[k] + 1);
 88                 continue; 
 89             }
 90             if (jud(i - 1, j, in ^ 1)) d[cur ^ 1][in ^ 1].push(t, d[cur][in].dp[k] + 1);////////////
 91         } else if(l || r) {
 92             int in2 = in;
 93             if (r) in2 ^= 1;/////////////
 94             int tmp = l + r;
 95             tp(t, j - 1, tmp), tp(t, j, 0);
 96             if (i + 1 <= n && jud(i - 1, j, in2) && jud(i, j - 1, 1 ^ in2) && jud(i, j, in2))
 97                 d[cur ^ 1][in2].push(t, d[cur][in].dp[k] + 1);
 98             t = d[cur][in].st[k];
 99             tp(t, j - 1, 0), tp(t, j, tmp);
100             if (j + 1 <= m && jud(i - 1, j, in2) && jud(i, j - 1, 1 ^ in2) && jud(i, j, 1 ^ in2))
101                  d[cur ^ 1][in2].push(t, d[cur][in].dp[k] + 1);
102         } else { ///////////
103             if (jud(i - 1, j, in) && jud(i, j - 1, in) && jud(i, j, in)) 
104                 d[cur ^ 1][in].push(t, d[cur][in].dp[k]);
105             tp(t, j - 1, 1), tp(t, j, 2);
106             if(i + 1 <= n && j + 1 <= m) {
107                 if (jud(i - 1, j, in) && jud(i, j - 1, in) && jud(i, j, 1 ^ in))
108                     d[cur ^ 1][in].push(t, d[cur][in].dp[k] + 1);
109             }
110         }
111     }
112 } 
113 
114 int main() {
115     int T;
116     scanf("%d", &T);
117     int cas = 0;
118     while (T-- > 0) {
119         scanf("%d%d", &n, &m);
120         memset(a, 0, sizeof a);
121         for (int i = 1; i <= n; ++i) {
122             scanf("%s", a[i] + 1);
123         }
124         ++n, ++m;
125         ex = 0, ey = 0;
126         for(int i = 1; i <= n; ++i) a[i][m] = '.';
127         for(int j = 1; j <= m; ++j) a[n][j] = '.';
128         for (int i = 1; i <= n; ++i)
129             for (int j = 1; j <= m; ++j) if (a[i][j] == 'o')
130                 ex = i, ey = j;
131         
132         int cur = 0;
133         d[0][0].init();
134         d[0][1].init();
135         d[0][0].push(0, 0);
136         ans = (int)1e9;
137         for (int i = 1; i <= n; ++i) {
138             for (int j = 1; j <= m; ++j) {
139                 d[cur ^ 1][0].init();
140                 d[cur ^ 1][1].init();
141                 blank(i, j, cur, 0);
142                 blank(i, j, cur, 1);
143                 cur ^= 1;
144             }
145             for (int j = 0; j < d[cur][0].cnt; ++j)
146                 d[cur][0].st[j] <<= 2;
147             for (int j = 0; j < d[cur][1].cnt; ++j)
148                 d[cur][1].st[j] <<= 2;
149         }
150         printf("Case #%d: ", ++cas);
151         if (ans == (int)1e9) puts("-1");
152         else printf("%d\n", ans);
153     }
154     return 0;
155 }
View Code

 

posted @ 2015-07-14 21:09  mithrilhan  阅读(246)  评论(0编辑  收藏  举报