[Description]
Given an n * m gird that has some blocked cells. Find how many paths visit each unblocked cell exactly once from the left low cell to the right low cell in that map.
有个 n行 ,m列的网格 ,有的格子有障碍物 ,其他的则可以行走 .问有多少条从左下角到右下角的路满足 :路经过了所有的可以行走的格子恰好一次 .
[Solution]
标准的基于连通性状态压缩DP问题。以格子一步一步的DP,设计一个m+1的插头状态并记下连通性。程序比较复杂,在2008年国家集训队陈丹琦的论文《基于连通性状态压缩的动态规划问题》中有非常详尽的介绍,这里就不多说了。
丑陋的源代码:
Given an n * m gird that has some blocked cells. Find how many paths visit each unblocked cell exactly once from the left low cell to the right low cell in that map.
有个 n行 ,m列的网格 ,有的格子有障碍物 ,其他的则可以行走 .问有多少条从左下角到右下角的路满足 :路经过了所有的可以行走的格子恰好一次 .
[Solution]
标准的基于连通性状态压缩DP问题。以格子一步一步的DP,设计一个m+1的插头状态并记下连通性。程序比较复杂,在2008年国家集训队陈丹琦的论文《基于连通性状态压缩的动态规划问题》中有非常详尽的介绍,这里就不多说了。
丑陋的源代码:
1
#include
<
iostream
>
2 #include < cstring >
3 #include < cstdlib >
4 #include < cstdio >
5 using namespace std;
6
7 #define MODIFY(A,B) (((B)<<(((A)-1)*2)))
8 #define GET(S,A) (((S)>>(((A)-1)*2))&3)
9 #define PRIME 999983
10
11 int n,m;
12 char a[ 13 ][ 14 ];
13 long long f[ 2 ][ 60000 ];
14 int now1,cnt,lin[ 60000 ],lef;
15 int g[ 1000000 ],next[ 100000 ],end[ 100000 ],va[ 100000 ],gcnt;
16 int endx,endy,startx,starty;
17 int gai;
18 int last,now;
19
20 inline int getp( int x)
21 {
22 int t = x % PRIME;
23 for ( int i = g[t];i;i = next[i])
24 if (x == end[i])
25 return va[i];
26 return 0 ;
27 }
28
29 void dfs( int step)
30 {
31 if (step > m + 1 )
32 {
33 if (lef)
34 return ;
35 cnt ++ ; lin[cnt] = now1;
36 int t = now1 % PRIME;
37 gcnt ++ ; end[gcnt] = now1; va[gcnt] = cnt; next[gcnt] = g[t]; g[t] = gcnt;
38 return ;
39 }
40 dfs(step + 1 );
41
42 lef ++ ;
43 if (lef <= ((m + 1 ) >> 1 ))
44 {
45 now1 += ( 1 << ((step - 1 ) * 2 ));
46 dfs(step + 1 );
47 now1 -= ( 1 << ((step - 1 ) * 2 ));
48 }
49 lef -- ;
50
51 if (lef)
52 {
53 lef -- ;
54 now1 += ( 2 << ((step - 1 ) * 2 ));
55 dfs(step + 1 );
56 now1 -= ( 2 << ((step - 1 ) * 2 ));
57 lef ++ ;
58 }
59 }
60
61 void prework()
62 {
63 dfs( 1 );
64 int tol = 0 ;
65 for ( int i = 1 ;i <= n;i ++ )
66 for ( int j = 1 ;j <= m;j ++ )
67 if (a[i][j] == ' . ' )
68 tol ++ ;
69 if (tol == 1 )
70 {
71 printf( " 0\n " );
72 exit( 0 );
73 }
74 bool flag = true ;
75 for ( int i = 1 ;i <= n;i ++ )
76 {
77 for ( int j = 1 ;j <= m;j ++ )
78 if (a[i][j] == ' . ' )
79 {
80 if (j == m)
81 {
82 printf( " 0\n " );
83 exit( 0 );
84 }
85 int t = 0 ;
86 t += MODIFY(j, 1 ) + MODIFY(j + 1 , 2 );
87 f[ 1 ][getp(t)] = 1 ;
88 startx = i; starty = j;
89 flag = false ;
90 break ;
91 }
92 if ( ! flag)
93 break ;
94 }
95 flag = true ;
96 for ( int i = n;i >= 1 ;i -- )
97 {
98 for ( int j = m;j >= 1 ;j -- )
99 if (a[i][j] == ' . ' )
100 {
101 endx = i; endy = j;
102 flag = false ;
103 break ;
104 }
105 if ( ! flag)
106 break ;
107 }
108 if (endy == 1 )
109 {
110 printf( " 0\n " );
111 exit( 0 );
112 }
113 }
114
115 long long ans;
116
117 void refresh( int x, int y, int _s)
118 {
119 long long zhi = f[last][_s];
120 int s = lin[_s];
121 y ++ ;
122 if (y > m) {y = 1 ;x ++ ;}
123 if (x == endx && y == endy)
124 {
125 int t1 = MODIFY( 1 , 1 ) + MODIFY(m + 1 , 2 );
126 int t2 = MODIFY( 1 , 1 ) + MODIFY(m, 2 );
127 if (s == t1 || s == t2)
128 ans += zhi;
129 return ;
130 }
131 if (y == 1 )
132 {
133 if (a[x][y] == ' # ' )
134 {
135 if (GET(s, 1 ) == 0 )
136 {
137 int news = ((s << 2 ) & gai);
138 f[now][getp(news)] += zhi;
139 }
140 }
141 else
142 {
143 if (GET(s, 1 ) == 0 )
144 {
145 int news = ((s << 2 ) & gai);
146 news += MODIFY( 1 , 1 ) + MODIFY( 2 , 2 );
147 f[now][getp(news)] += zhi;
148 }
149 else
150 {
151 int news = (((s - MODIFY( 1 , 1 )) << 2 ) & gai);
152 f[now][getp(news + MODIFY( 1 , 1 ))] += zhi;
153 f[now][getp(news + MODIFY( 2 , 1 ))] += zhi;
154 }
155 }
156 }
157 else
158 {
159 if (a[x][y] == ' # ' )
160 {
161 if (GET(s,y) == 0 && GET(s,y + 1 ) == 0 )
162 f[now][getp(s)] += zhi;
163 }
164 else
165 {
166 int t1 = GET(s,y),t2 = GET(s,y + 1 );
167 if (t1 != 0 && t2 != 0 )
168 {
169 if (t1 == 1 && t2 == 1 )
170 {
171 int news = s - MODIFY(y, 1 ) - MODIFY(y + 1 , 1 );
172 int left = 0 ;
173 for ( int i = y + 2 ;i <= m + 1 ;i ++ )
174 if (GET(news,i) == 1 )
175 left ++ ;
176 else if (GET(news,i) == 2 )
177 {
178 if ( ! left)
179 {
180 news = news - MODIFY(i, 2 ) + MODIFY(i, 1 );
181 break ;
182 }
183 left -- ;
184 }
185 f[now][getp(news)] += zhi;
186 }
187 else if (t1 == 2 && t2 == 1 )
188 {
189 int t = getp(s - MODIFY(y, 2 ) - MODIFY(y + 1 , 1 ));
190 f[now][t] += zhi;
191 }
192 else if (t1 == 2 && t2 == 2 )
193 {
194 int news = s - MODIFY(y, 2 ) - MODIFY(y + 1 , 2 );
195 int left = 0 ;
196 for ( int i = y - 1 ;i >= 1 ;i -- )
197 if (GET(news,i) == 2 )
198 left ++ ;
199 else if (GET(news,i) == 1 )
200 {
201 if ( ! left)
202 {
203 news = news - MODIFY(i, 1 ) + MODIFY(i, 2 );
204 break ;
205 }
206 left -- ;
207 }
208 f[now][getp(news)] += zhi;
209 }
210 }
211 if (t1 == 0 && t2 != 0 && y != m)
212 f[now][getp(s)] += zhi;
213 if (t1 != 0 && t2 == 0 && x != n)
214 f[now][getp(s)] += zhi;
215 if (t1 == 0 && t2 == 0 && y != m && x != n)
216 f[now][getp(s + MODIFY(y, 1 ) + MODIFY(y + 1 , 2 ))] += zhi;
217 if (t1 == 0 && t2 != 0 && x != n)
218 f[now][getp(s - MODIFY(y + 1 ,t2) + MODIFY(y,t2))] += zhi;
219 if (t1 != 0 && t2 == 0 && y != m)
220 f[now][getp(s - MODIFY(y,t1) + MODIFY(y + 1 ,t1))] += zhi;
221 }
222 }
223 }
224
225 void work()
226 {
227 ans = 0 ;
228 int i = startx,j = starty;
229 now = 0 ,last = 1 ;
230 while ( true )
231 {
232 memset(f[now] + 1 , 0 , sizeof ( long long ) * cnt);
233 if (i == endx && j == endy)
234 break ;
235 else
236 for ( int k = 1 ;k <= cnt;k ++ )
237 if (f[last][k])
238 refresh(i,j,k);
239 j ++ ; if (j > m) {i ++ ;j = 1 ;}
240 now ^= 1 ; last ^= 1 ;
241 }
242 printf( " %I64d\n " ,ans);
243 }
244
245 void init()
246 {
247 n = m = 0 ;
248 memset(a, 0 , sizeof (a));
249 memset(f, 0 , sizeof (f));
250 now1 = cnt = lef = 0 ;
251 gcnt = 0 ;
252 memset(g, 0 , sizeof (g));
253 endx = endy = startx = starty = 0 ;
254 gai = 0 ;
255 last = now = 0 ;
256 ans = 0 ;
257 }
258
259 int main()
260 {
261 while ( true )
262 {
263 init();
264 scanf( " %d%d " , & n, & m);
265 if (n == 0 ) break ;
266 for ( int i = 1 ;i <= n;i ++ )
267 scanf( " %s " ,a[i] + 1 );
268 gai = ( 1 << ((m + 1 ) * 2 )) - 1 ;
269 prework();
270 work();
271 }
272 }
2 #include < cstring >
3 #include < cstdlib >
4 #include < cstdio >
5 using namespace std;
6
7 #define MODIFY(A,B) (((B)<<(((A)-1)*2)))
8 #define GET(S,A) (((S)>>(((A)-1)*2))&3)
9 #define PRIME 999983
10
11 int n,m;
12 char a[ 13 ][ 14 ];
13 long long f[ 2 ][ 60000 ];
14 int now1,cnt,lin[ 60000 ],lef;
15 int g[ 1000000 ],next[ 100000 ],end[ 100000 ],va[ 100000 ],gcnt;
16 int endx,endy,startx,starty;
17 int gai;
18 int last,now;
19
20 inline int getp( int x)
21 {
22 int t = x % PRIME;
23 for ( int i = g[t];i;i = next[i])
24 if (x == end[i])
25 return va[i];
26 return 0 ;
27 }
28
29 void dfs( int step)
30 {
31 if (step > m + 1 )
32 {
33 if (lef)
34 return ;
35 cnt ++ ; lin[cnt] = now1;
36 int t = now1 % PRIME;
37 gcnt ++ ; end[gcnt] = now1; va[gcnt] = cnt; next[gcnt] = g[t]; g[t] = gcnt;
38 return ;
39 }
40 dfs(step + 1 );
41
42 lef ++ ;
43 if (lef <= ((m + 1 ) >> 1 ))
44 {
45 now1 += ( 1 << ((step - 1 ) * 2 ));
46 dfs(step + 1 );
47 now1 -= ( 1 << ((step - 1 ) * 2 ));
48 }
49 lef -- ;
50
51 if (lef)
52 {
53 lef -- ;
54 now1 += ( 2 << ((step - 1 ) * 2 ));
55 dfs(step + 1 );
56 now1 -= ( 2 << ((step - 1 ) * 2 ));
57 lef ++ ;
58 }
59 }
60
61 void prework()
62 {
63 dfs( 1 );
64 int tol = 0 ;
65 for ( int i = 1 ;i <= n;i ++ )
66 for ( int j = 1 ;j <= m;j ++ )
67 if (a[i][j] == ' . ' )
68 tol ++ ;
69 if (tol == 1 )
70 {
71 printf( " 0\n " );
72 exit( 0 );
73 }
74 bool flag = true ;
75 for ( int i = 1 ;i <= n;i ++ )
76 {
77 for ( int j = 1 ;j <= m;j ++ )
78 if (a[i][j] == ' . ' )
79 {
80 if (j == m)
81 {
82 printf( " 0\n " );
83 exit( 0 );
84 }
85 int t = 0 ;
86 t += MODIFY(j, 1 ) + MODIFY(j + 1 , 2 );
87 f[ 1 ][getp(t)] = 1 ;
88 startx = i; starty = j;
89 flag = false ;
90 break ;
91 }
92 if ( ! flag)
93 break ;
94 }
95 flag = true ;
96 for ( int i = n;i >= 1 ;i -- )
97 {
98 for ( int j = m;j >= 1 ;j -- )
99 if (a[i][j] == ' . ' )
100 {
101 endx = i; endy = j;
102 flag = false ;
103 break ;
104 }
105 if ( ! flag)
106 break ;
107 }
108 if (endy == 1 )
109 {
110 printf( " 0\n " );
111 exit( 0 );
112 }
113 }
114
115 long long ans;
116
117 void refresh( int x, int y, int _s)
118 {
119 long long zhi = f[last][_s];
120 int s = lin[_s];
121 y ++ ;
122 if (y > m) {y = 1 ;x ++ ;}
123 if (x == endx && y == endy)
124 {
125 int t1 = MODIFY( 1 , 1 ) + MODIFY(m + 1 , 2 );
126 int t2 = MODIFY( 1 , 1 ) + MODIFY(m, 2 );
127 if (s == t1 || s == t2)
128 ans += zhi;
129 return ;
130 }
131 if (y == 1 )
132 {
133 if (a[x][y] == ' # ' )
134 {
135 if (GET(s, 1 ) == 0 )
136 {
137 int news = ((s << 2 ) & gai);
138 f[now][getp(news)] += zhi;
139 }
140 }
141 else
142 {
143 if (GET(s, 1 ) == 0 )
144 {
145 int news = ((s << 2 ) & gai);
146 news += MODIFY( 1 , 1 ) + MODIFY( 2 , 2 );
147 f[now][getp(news)] += zhi;
148 }
149 else
150 {
151 int news = (((s - MODIFY( 1 , 1 )) << 2 ) & gai);
152 f[now][getp(news + MODIFY( 1 , 1 ))] += zhi;
153 f[now][getp(news + MODIFY( 2 , 1 ))] += zhi;
154 }
155 }
156 }
157 else
158 {
159 if (a[x][y] == ' # ' )
160 {
161 if (GET(s,y) == 0 && GET(s,y + 1 ) == 0 )
162 f[now][getp(s)] += zhi;
163 }
164 else
165 {
166 int t1 = GET(s,y),t2 = GET(s,y + 1 );
167 if (t1 != 0 && t2 != 0 )
168 {
169 if (t1 == 1 && t2 == 1 )
170 {
171 int news = s - MODIFY(y, 1 ) - MODIFY(y + 1 , 1 );
172 int left = 0 ;
173 for ( int i = y + 2 ;i <= m + 1 ;i ++ )
174 if (GET(news,i) == 1 )
175 left ++ ;
176 else if (GET(news,i) == 2 )
177 {
178 if ( ! left)
179 {
180 news = news - MODIFY(i, 2 ) + MODIFY(i, 1 );
181 break ;
182 }
183 left -- ;
184 }
185 f[now][getp(news)] += zhi;
186 }
187 else if (t1 == 2 && t2 == 1 )
188 {
189 int t = getp(s - MODIFY(y, 2 ) - MODIFY(y + 1 , 1 ));
190 f[now][t] += zhi;
191 }
192 else if (t1 == 2 && t2 == 2 )
193 {
194 int news = s - MODIFY(y, 2 ) - MODIFY(y + 1 , 2 );
195 int left = 0 ;
196 for ( int i = y - 1 ;i >= 1 ;i -- )
197 if (GET(news,i) == 2 )
198 left ++ ;
199 else if (GET(news,i) == 1 )
200 {
201 if ( ! left)
202 {
203 news = news - MODIFY(i, 1 ) + MODIFY(i, 2 );
204 break ;
205 }
206 left -- ;
207 }
208 f[now][getp(news)] += zhi;
209 }
210 }
211 if (t1 == 0 && t2 != 0 && y != m)
212 f[now][getp(s)] += zhi;
213 if (t1 != 0 && t2 == 0 && x != n)
214 f[now][getp(s)] += zhi;
215 if (t1 == 0 && t2 == 0 && y != m && x != n)
216 f[now][getp(s + MODIFY(y, 1 ) + MODIFY(y + 1 , 2 ))] += zhi;
217 if (t1 == 0 && t2 != 0 && x != n)
218 f[now][getp(s - MODIFY(y + 1 ,t2) + MODIFY(y,t2))] += zhi;
219 if (t1 != 0 && t2 == 0 && y != m)
220 f[now][getp(s - MODIFY(y,t1) + MODIFY(y + 1 ,t1))] += zhi;
221 }
222 }
223 }
224
225 void work()
226 {
227 ans = 0 ;
228 int i = startx,j = starty;
229 now = 0 ,last = 1 ;
230 while ( true )
231 {
232 memset(f[now] + 1 , 0 , sizeof ( long long ) * cnt);
233 if (i == endx && j == endy)
234 break ;
235 else
236 for ( int k = 1 ;k <= cnt;k ++ )
237 if (f[last][k])
238 refresh(i,j,k);
239 j ++ ; if (j > m) {i ++ ;j = 1 ;}
240 now ^= 1 ; last ^= 1 ;
241 }
242 printf( " %I64d\n " ,ans);
243 }
244
245 void init()
246 {
247 n = m = 0 ;
248 memset(a, 0 , sizeof (a));
249 memset(f, 0 , sizeof (f));
250 now1 = cnt = lef = 0 ;
251 gcnt = 0 ;
252 memset(g, 0 , sizeof (g));
253 endx = endy = startx = starty = 0 ;
254 gai = 0 ;
255 last = now = 0 ;
256 ans = 0 ;
257 }
258
259 int main()
260 {
261 while ( true )
262 {
263 init();
264 scanf( " %d%d " , & n, & m);
265 if (n == 0 ) break ;
266 for ( int i = 1 ;i <= n;i ++ )
267 scanf( " %s " ,a[i] + 1 );
268 gai = ( 1 << ((m + 1 ) * 2 )) - 1 ;
269 prework();
270 work();
271 }
272 }