通道:http://poj.org/problem?id=1739
题意:左下角走到右下角路径数,单回路。做法就是我们新添2行后寻找回路就可以啦 。
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 int ex, ey; 34 35 int find_pos(long long s, int p) { 36 return (s >> (p << 1)) & 3; 37 } 38 39 void tp(long long &s, int p, long long v) { 40 s &= (~(3ll << (p << 1))); 41 s |= (v << (p << 1)); 42 } 43 44 int find_r(long long s, int p) { 45 int cnt = 0; 46 for(int i = p; i <= m; ++i) { 47 if(find_pos(s, i) == 1) ++cnt; 48 else if(find_pos(s, i) == 2) --cnt; 49 if(!cnt) return i; 50 } 51 } 52 53 int find_l(long long s, int p) { 54 int cnt = 0; 55 for(int i = p; i >= 0; --i) { 56 if(find_pos(s, i) == 2) ++cnt; 57 else if(find_pos(s, i) == 1) --cnt; 58 if(!cnt) return i; 59 } 60 } 61 62 void blank(int i, int j, int cur) { 63 for(int k = 0; k < d[cur].cnt; ++k) { 64 long long t = d[cur].st[k]; 65 int l = find_pos(t, j - 1), r = find_pos(t, j); 66 if(l && r) { 67 if(l == 1 && r == 1) { 68 int tpos = find_r(t, j); 69 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1); 70 d[cur ^ 1].push(t, d[cur].dp[k]); 71 } else if(l == 2 && r == 1) { 72 tp(t, j - 1, 0); tp(t, j, 0); 73 d[cur ^ 1].push(t, d[cur].dp[k]); 74 } else if(l == 2 && r == 2) { 75 int tpos = find_l(t, j - 1); 76 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2); 77 d[cur ^ 1].push(t, d[cur].dp[k]); 78 } else { // 最后一个非障碍格子 79 tp(t, j - 1, 0); tp(t, j, 0); 80 // 2位为1代表有1个回路,4位为1代表有2个回路 81 if (!t) if (i == ex && j == ey) d[cur ^ 1].push(t, d[cur].dp[k]); 82 } 83 } else if(l) { 84 if(i < n) { 85 d[cur ^ 1].push(t, d[cur].dp[k]); 86 } 87 if(j < m) { 88 tp(t, j - 1, 0); tp(t, j, l); 89 d[cur ^ 1].push(t, d[cur].dp[k]); 90 } 91 } else if(r) { 92 if(j < m) { 93 d[cur ^ 1].push(t, d[cur].dp[k]); 94 } 95 if(i < n) { 96 tp(t, j - 1, r); tp(t, j, 0); 97 d[cur ^ 1].push(t, d[cur].dp[k]); 98 } 99 } else { // 新建 100 if(i < n && j < m) { 101 tp(t, j - 1, 1); tp(t, j, 2); 102 d[cur ^ 1].push(t, d[cur].dp[k]); 103 } 104 } 105 } 106 } 107 108 void block(int i, int j, int cur) { 109 for (int k = 0; k < d[cur].cnt; ++k) { 110 long long t = d[cur].st[k]; 111 int l = find_pos(t, j - 1), r = find_pos(t, j); 112 if (!l && !r) d[cur ^ 1].push(t, d[cur].dp[k]); 113 } 114 } 115 116 char str[17]; 117 int a[MAX_N][MAX_M]; 118 119 int main() { 120 while (2 == scanf("%d%d", &n, &m)) { 121 if (0 == m && 0 == m) break; 122 memset(a, 0, sizeof a); 123 for (int i = 1; i <= n; ++i) { 124 scanf("%s", str + 1); 125 for (int j = 1; j <= m; ++j) 126 a[i][j] = str[j] == '.'; 127 } 128 for (int i = 1; i <= m; ++i) 129 a[n + 2][i] = 1; 130 for (int i = 2; i < m; ++i) 131 a[n + 1][i] = 0; 132 a[n + 1][1] = a[n + 1][m] = 1; 133 int cur = 0; 134 long long ans = 0; 135 d[cur].init(); 136 d[cur].push(0, 1); 137 n = n + 2; 138 ex = n, ey = m; 139 for (int i = 1; i <= n; ++i) { 140 for (int j = 1; j <= m; ++j) { 141 d[cur ^ 1].init(); 142 if (a[i][j]) blank(i, j, cur); 143 else block(i, j, cur); 144 cur ^= 1; 145 } 146 for (int j = 0; j < d[cur].cnt; ++j) 147 d[cur].st[j] <<= 2; 148 } 149 for(int i = 0; i < d[cur].cnt; ++i) 150 ans += d[cur].dp[i]; 151 printf("%I64d\n", ans); 152 } 153 return 0; 154 }