【插头DP】HDU 1693 Eat the Trees

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

题意:多回路路径方案数,无障碍。

代码:

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

 

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