【插头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 }