【插头DP】 BZOJ 2331 地板

通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2331

题意:用L型的填满格子,有障碍。

思路:0表示该格无插头,1表示向内,2表示向外。

  (1)如果left插头和up插头都为0

     1.从未决策右边和下边格子引两条箭头

     2.从该格向未决策的右边引外插头

     3.从该格向未决策的下边引外插头

  (2)如果left插头或者up插头为0,如果有拐角,则按原方向转移。

      (3)如果left插头和up插头均为1,状态合法

 

代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 
  5 using namespace std;
  6 
  7 const int MAX_N = 103;
  8 const int MAX_M = 103;
  9 const int HASH = 100007;
 10 const int MAX_S = 1000007; 
 11 const int MOD = 20110520;
 12 
 13 const int mov[20] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
 14 
 15 struct node {
 16     int head[HASH], nxt[MAX_S], cnt;
 17     long long dp[MAX_S], st[MAX_S];
 18     void init() {
 19         memset(head, -1, sizeof head);
 20         cnt = 0;
 21     }
 22     void push(long long s, long long v) {
 23         int now = s % HASH; 
 24         for(int i = head[now]; ~i; i = nxt[i]) if(st[i] == s) {
 25             dp[i] = (dp[i] + v) % MOD;
 26             return ;
 27         }
 28         st[cnt] = s;      dp[cnt] = v;
 29         nxt[cnt] = head[now];
 30         head[now] = cnt++;
 31     }
 32 }d[2];
 33 
 34 int n, m;
 35 int ex, ey;
 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 long long ans1;
 65 
 66 void blank(int i, int j, int cur) {
 67     for(int k = 0; k < d[cur].cnt; ++k) {
 68         long long t = d[cur].st[k];
 69         int l = find_pos(t, j - 1), r = find_pos(t, j);
 70         if(l && r) {
 71             if(l == 1 && r == 1) {
 72                 tp(t, j - 1, 0); tp(t, j, 0); 
 73                 d[cur ^ 1].push(t, d[cur].dp[k]);
 74                 if (i == ex && j == ey) ans1 = (ans1 + d[cur].dp[k]) % MOD;
 75             } 
 76         } else if(l) {
 77             if(i < n && l == 1) {
 78                 tp(t, j - 1, 2); tp(t, j, 0);
 79                 d[cur ^ 1].push(t, d[cur].dp[k]);
 80             }
 81             if(j < m) {
 82                 t = d[cur].st[k];
 83                 tp(t, j - 1, 0); tp(t, j, l);
 84                 d[cur ^ 1].push(t, d[cur].dp[k]);
 85             }
 86             if(l == 2) {
 87                 t = d[cur].st[k];
 88                 tp(t, j - 1, 0); tp(t, j, 0);
 89                 d[cur ^ 1].push(t, d[cur].dp[k]);
 90                 if (i == ex && j == ey) ans1 = (ans1 + d[cur].dp[k]) % MOD;
 91             }
 92         } else if(r) {
 93             if(j < m && r == 1) {
 94                 tp(t, j - 1, 0); tp(t, j, 2);
 95                 d[cur ^ 1].push(t, d[cur].dp[k]);
 96             }
 97             if(i < n) {
 98                 t = d[cur].st[k];
 99                 tp(t, j - 1, r); tp(t, j, 0);
100                 d[cur ^ 1].push(t, d[cur].dp[k]);
101             }
102             if(r == 2) {
103                 t = d[cur].st[k];
104                 tp(t, j - 1, 0); tp(t, j, 0);
105                 d[cur ^ 1].push(t, d[cur].dp[k]);
106                 if (i == ex && j == ey) ans1 = (ans1 + d[cur].dp[k]) % MOD;
107             }
108             
109             
110         } else { // 新建 
111             if(i < n && j < m) {
112                 tp(t, j - 1, 2); tp(t, j, 2);
113                 d[cur ^ 1].push(t, d[cur].dp[k]);
114             }
115             if (i < n) {
116                 t = d[cur].st[k];
117                 tp(t, j - 1, 1); tp(t, j, 0);
118                 d[cur ^ 1].push(t, d[cur].dp[k]);
119             }
120             if (j < m) {
121                 t = d[cur].st[k];
122                 tp(t, j - 1, 0); tp(t, j, 1);
123                 d[cur ^ 1].push(t, d[cur].dp[k]);
124             }          
125         }
126     }
127 } 
128 
129 void block(int i, int j, int cur) {
130     for (int k = 0; k < d[cur].cnt; ++k) {
131         long long t = d[cur].st[k];
132         int l = find_pos(t, j - 1), r = find_pos(t, j);
133         if (!l && !r) d[cur ^ 1].push(t, d[cur].dp[k]);
134     }
135 } 
136 
137 char str[107];
138 int a[MAX_N][MAX_M], z[MAX_N][MAX_M];
139 
140 int main() {    
141     while (2 == scanf("%d%d", &n, &m)) {
142         memset(a, 0, sizeof a);
143         for (int i = 1; i <= n; ++i) {
144             scanf("%s", str + 1);
145             for (int j = 1; j <= m; ++j) {
146                 if (str[j] == '_') {
147                     a[i][j] = 1;
148                     ex = i, ey = j;
149                 }
150             }
151         }
152            if (n < m) {
153                for (int i = 1; i <= n; ++i)
154                    for (int j = 1; j <= m; ++j)
155                        z[j][i] = a[i][j];
156                swap(ex, ey); swap(n, m);
157                memcpy(a, z, sizeof z);
158            }
159            int cur = 0;
160         d[cur].init();
161         d[cur].push(0, 1);
162         ans1 = 0;
163         for (int i = 1; i <= n; ++i) {
164             for (int j = 1; j <= m; ++j) {
165                 d[cur ^ 1].init();
166                 if (a[i][j]) blank(i, j, cur);
167                 else block(i, j, cur);
168                 cur ^= 1;
169             }
170             for (int j = 0; j < d[cur].cnt; ++j)
171                 d[cur].st[j] <<= 2;
172         }
173         ans1 %= MOD;
174         printf("%d\n", ans1);
175     }
176     return 0;
177 }
View Code

 

转载于:https://www.cnblogs.com/Rojo/p/4646514.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值