【插头DP】POJ 3133 Manhattan Wiring

通道:http://poj.org/problem?id=3133

题意:2条简单路径,不相交,最小权值,可选可不选,有障碍。

思路:构造2条轮廓线分辨表示两条路径即可。

代码:

  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];
 32 
 33 int n, m;
 34 int a[MAX_N][MAX_M];
 35 
 36 int find_pos(long long s, int p) {
 37     return s >> mov[p] & 3;
 38 }
 39 
 40 void tp(long long &s, int p, long long v) {
 41     s &= ~(3ll << mov[p]);
 42     s |= v << mov[p];
 43 }
 44 
 45 
 46 int find_r(long long s, int p) {
 47     int cnt = 0;
 48     for(int i = p; i <= m; ++i) {
 49         if(find_pos(s, i) == 1) ++cnt;
 50         else if(find_pos(s, i) == 2) --cnt;
 51         if(!cnt) return i;
 52     }
 53 }
 54 
 55 int find_l(long long s, int p) {
 56     int cnt = 0;
 57     for(int i = p; i >= 0; --i) {
 58         if(find_pos(s, i) == 2) ++cnt;
 59         else if(find_pos(s, i) == 1) --cnt;
 60         if(!cnt) return i;
 61     }
 62 }
 63 
 64 void blank(int i, int j, int cur) {
 65     for(int k = 0; k < d[cur].cnt; ++k) {
 66         long long t = d[cur].st[k];
 67         int l = find_pos(t, j - 1), r = find_pos(t, j);
 68         if (a[i][j] >= 2) {
 69             if (l && r) continue;
 70             int now = a[i][j] == 2 ? 1 : 2;
 71             if (!l && !r) {
 72                 if (i < n) {
 73                     tp(t, j - 1, now); tp(t, j, 0);
 74                     d[cur ^ 1].push(t, d[cur].dp[k]);
 75                 }
 76                 if (j < m) {
 77                     t = d[cur].st[k];
 78                     tp(t, j - 1, 0); tp(t, j, now);
 79                     d[cur ^ 1].push(t, d[cur].dp[k]);
 80                 }
 81             } else {
 82                 if (l + r != now) continue;
 83                 tp(t, j - 1, 0); tp(t, j, 0);
 84                 d[cur ^ 1].push(t, d[cur].dp[k]);
 85             }
 86             continue;
 87         }
 88         if(l && r) {
 89             if (l != r) continue;
 90             tp(t, j - 1, 0); tp(t, j, 0);
 91             d[cur ^ 1].push(t, d[cur].dp[k] + 1);
 92         } else if(l || r) {
 93             int now = l + r;
 94             if(i < n) {
 95                 tp(t, j - 1, now); tp(t, j, 0);
 96                 d[cur ^ 1].push(t, d[cur].dp[k] + 1);
 97             }
 98             if(j < m) {
 99                 t = d[cur].st[k];
100                 tp(t, j - 1, 0); tp(t, j, now);
101                 d[cur ^ 1].push(t, d[cur].dp[k] + 1);
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, 1);
107                 d[cur ^ 1].push(t, d[cur].dp[k] + 1);
108                 t = d[cur].st[k];
109                 tp(t, j - 1, 2); tp(t, j, 2);
110                 d[cur ^ 1].push(t, d[cur].dp[k] + 1);
111             }
112         }
113     }
114 } 
115 
116 void block(int i, int j, int cur) {
117     for (int k = 0; k < d[cur].cnt; ++k) {
118         long long t = d[cur].st[k];
119         int l = find_pos(t, j - 1), r = find_pos(t, j);
120         if (!l && !r) d[cur ^ 1].push(t, d[cur].dp[k]);
121     }
122 } 
123 
124 int main() {
125     while (2 == scanf("%d%d", &n, &m)) {
126         if (0 == n && 0 == m) break;
127         memset(a, 0, sizeof a);
128         for (int i = 1; i <= n; ++i)
129             for (int j = 1; j <= m; ++j)
130                 scanf("%d", &a[i][j]);
131         int cur = 0;
132         d[cur].init();
133         d[cur].push(0, 0); 
134         for (int i = 1; i <= n; ++i) {
135             for (int j = 1; j <= m; ++j) {
136                 d[cur ^ 1].init();
137                 if (a[i][j] == 1) block(i, j, cur);
138                 else blank(i, j, cur);
139                 cur ^= 1;
140             }
141             for (int j = 0; j < d[cur].cnt; ++j)
142                 d[cur].st[j] <<= 2;
143         }
144         int ans = (int) 1e9;
145         for (int i = 0; i < d[cur].cnt; ++i)     
146             ans = min((long long)ans, d[cur].dp[i]);
147         if (ans == (int)1e9) puts("0");
148         else printf("%d\n", ans + 2);
149     }
150     return 0;
151 }
View Code

 

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