【插头DP】HDU 4285 circuits
通道:http://acm.hdu.edu.cn/showproblem.php?pid=4285
题意:多回路, 有障碍K回路问题。
代码:
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 = 300007; 10 const int MAX_S = 1000007 + 10; 11 const int MOD = 1000000007; 12 13 14 const int mov[20] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}; 15 16 struct node { 17 int head[HASH], nxt[MAX_S]; 18 long long dp[MAX_S], st[MAX_S]; 19 long long num[MAX_S]; 20 int cnt; 21 void init() { 22 memset(head, -1, sizeof head); 23 cnt = 0; 24 } 25 void push(long long s, long long v, long long val) { 26 int now = s % HASH; 27 for(int i = head[now]; ~i; i = nxt[i]) if(st[i] == s && val == num[i]) { 28 dp[i] = (dp[i] + v) % MOD; 29 return ; 30 } 31 st[cnt] = s; dp[cnt] = v; num[cnt] = val; 32 nxt[cnt] = head[now]; 33 head[now] = cnt++; 34 } 35 }d[2]; 36 37 int n, m, K; 38 39 int find_pos(long long s, int p) { 40 return (s >> (p << 1)) & 3; 41 } 42 43 void tp(long long &s, int p, long long v) { 44 s &= (~(3ll << (p << 1))); 45 s |= (v << (p << 1)); 46 } 47 48 int find_r(long long s, int p) { 49 int cnt = 0; 50 for(int i = p; i <= m; ++i) { 51 if(find_pos(s, i) == 1) ++cnt; 52 else if(find_pos(s, i) == 2) --cnt; 53 if(!cnt) return i; 54 } 55 } 56 57 int find_l(long long s, int p) { 58 int cnt = 0; 59 for(int i = p; i >= 0; --i) { 60 if(find_pos(s, i) == 2) ++cnt; 61 else if(find_pos(s, i) == 1) --cnt; 62 if(!cnt) return i; 63 } 64 } 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 int tpos = find_r(t, j); 73 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1); 74 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 75 } else if(l == 2 && r == 1) { 76 tp(t, j - 1, 0); tp(t, j, 0); 77 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 78 } else if(l == 2 && r == 2) { 79 int tpos = find_l(t, j - 1); 80 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2); 81 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 82 } else { 83 int count = 0; 84 for (int z = j - 2; z >= 0; --z) if (find_pos(t, z)) ++count; 85 if (count & 1) continue; 86 for (int z = j + 1; z <= m; ++z) if (find_pos(t, z)) ++count; 87 if (count & 1) continue; 88 tp(t, j - 1, 0); tp(t, j, 0); 89 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k] + 1); 90 } 91 } else if(l) { 92 if(i < n) { 93 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 94 } 95 if(j < m) { 96 tp(t, j - 1, 0); tp(t, j, l); 97 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 98 } 99 } else if(r) { 100 if(j < m) { 101 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 102 } 103 if(i < n) { 104 tp(t, j - 1, r); tp(t, j, 0); 105 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 106 } 107 } else { // 新建 108 if(i < n && j < m) { 109 tp(t, j - 1, 1); tp(t, j, 2); 110 d[cur ^ 1].push(t, d[cur].dp[k], d[cur].num[k]); 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], d[cur].num[k]); 121 } 122 } 123 124 char str[17]; 125 int a[MAX_N][MAX_M]; 126 127 int main() { 128 int T; 129 scanf("%d", &T); 130 while (T-- > 0) { 131 scanf("%d%d%d", &n, &m, &K); 132 memset(a, 0, sizeof a); 133 int ex = -1; 134 for (int i = 1; i <= n; ++i) { 135 scanf("%s", str + 1); 136 for (int j = 1; j <= m; ++j) { 137 if (str[j] == '.') { 138 a[i][j] = 1; 139 ex = i; 140 } 141 } 142 } 143 if (ex == -1) { 144 if (K == 0) puts("1"); 145 else puts("0"); 146 } else { 147 int cur = 0; 148 d[cur].init(); 149 memset(d[cur].num, 0, sizeof d[cur].num); 150 d[cur].push(0, 1, 0); 151 long long ans = 0; 152 for (int i = 1; i <= n; ++i) { 153 for (int j = 1; j <= m; ++j) { 154 d[cur ^ 1].init(); 155 if (a[i][j]) blank(i, j, cur); 156 else block(i, j, cur); 157 cur ^= 1; 158 } 159 for(int k = 0; k < d[cur].cnt; ++k) { 160 d[cur].st[k] <<= 2; 161 } 162 } 163 // for (int i = 0; i < d[cur].cnt; ++i) 164 // printf("%d %d %d %d\n", i, d[cur].st[i], d[cur].st[i] >> mov[m + 2], d[cur].dp[i]); 165 for (int i = 0; i < d[cur].cnt; ++i) if (d[cur].num[i] == K) 166 ans = (ans + d[cur].dp[i]) % MOD; 167 printf("%I64d\n", ans); 168 } 169 } 170 return 0; 171 } 172 173 /* 174 175 100 176 177 4 4 1 178 **.. 179 .... 180 .... 181 .... 182 183 4 4 1 184 .... 185 .... 186 .... 187 .... 188 189 4 4 2 190 .... 191 .... 192 .... 193 .... 194 195 4 4 4 196 .... 197 .... 198 .... 199 .... 200 201 */
TAG:控制好HASH啊。