楼教主男人八题之一。。。 

题目大意:

求从左下角经过所有非障碍点一次到达右下角的方案数

 

这里不是求回路,但是我们可以考虑,在最下面一行再增加一行,那么就可以当做求此时左下角到右下角的回路总数,那么就转化成了陈丹琦论文的URAL1519的

方法了

但是最后一行添加的格子必须是最后一条直线跑的,也就是除了左下角和右下角中间的点只能有水平方向上的插头

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 
  6 using namespace std;
  7 #define ll long long
  8 const int HASH = 10007;
  9 const int STATE = 1000010;
 10 const int MAXD = 15;
 11 int  n , m , enx , eny;
 12 int code[MAXD] , mp[MAXD][MAXD];
 13 bool flag[MAXD][MAXD];//标记位,标记当前点能否作为最终点
 14 ll ans = 0;
 15 struct HASHMAP{
 16     int head[HASH] , next[STATE] , state[STATE] , size;
 17     ll f[STATE];
 18 
 19     void init(){
 20         size = 0;
 21         memset(head , -1 , sizeof(head));
 22     }
 23 
 24     void push_in(int st , ll sum){
 25         int h = st%HASH;
 26         for(int i = head[h] ; ~i ; i=next[i]){
 27             if(st == state[i]){
 28                 f[i]+=sum;
 29                 return ;
 30             }
 31         }
 32         f[size]=sum;
 33         state[size] = st;
 34         next[size] = head[h];
 35         head[h] = size++;
 36     }
 37 }hashmap[2];
 38 
 39 int num = 0;//记录共有的插头数量
 40 void decode(int *code , int m , int st)
 41 {
 42     num = 0;
 43     for(int i=m ; i>=0 ; i--){
 44         code[i] = st&3;
 45         st>>=2;
 46         if(code[i]) num++;
 47     }
 48 }
 49 
 50 int encode(int *code , int m)
 51 {
 52     int st=0;
 53     for(int i=0 ; i<=m ; i++){
 54         st<<=2;
 55         st |= code[i];
 56     }
 57     return st;
 58 }
 59 
 60 void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧
 61 {
 62     for(int i=m ; i>=0 ; i--) code[i] = code[i-1];
 63     code[0] = 0;
 64 }
 65 
 66 void dpblank(int i , int j , int cur)
 67 {
 68     int k , left , up;
 69     for(k=0 ; k<hashmap[cur].size ; k++){
 70         decode(code , m , hashmap[cur].state[k]);
 71         left = code[j-1];
 72         up = code[j];
 73       //  cout<<"chatou: "<<i<<" "<<j<<" "<<left<<" "<<up<<endl;
 74         if(!left && !up){
 75             if(mp[i][j+1] && mp[i-1][j]){ //不断向上转移
 76                 code[j-1] = 1 , code[j] = 2;
 77                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
 78             }
 79         }
 80         else if(!left && up){
 81             if(mp[i][j+1]) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
 82             if(mp[i-1][j]){
 83                 code[j-1] = up , code[j] = 0;
 84                 if(j == m) shift(code , m);
 85                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
 86             }
 87         }
 88         else if(left && !up){
 89             if(mp[i-1][j]){
 90                 if(j == m)  shift(code , m);
 91                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
 92             }
 93             if(mp[i][j+1]){
 94                 code[j-1] = 0 , code[j] = left;
 95                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
 96             }
 97         }
 98         else if(left==1 && up == 1){
 99             int cnt = 1;
100             for(int v=j+1 ; v<=m ; v++){
101                 if(code[v]==1)cnt++;
102                 if(code[v]==2)cnt--;
103                 if(!cnt){
104                     code[v]=1;
105                     break;
106                 }
107             }
108             code[j-1] = code[j] = 0;
109             if(j == m) shift(code , m);
110             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
111         }
112         else if(left == 2 && up == 2){
113             int cnt=1;
114             for(int v=j-2 ; v>=1 ; v--){
115                 if(code[v]==2)cnt++;
116                 if(code[v]==1)cnt--;
117                 if(!cnt){
118                     code[v]=2;
119                     break;
120                 }
121             }
122             code[j-1] = code[j] = 0;
123             if(j == m) shift(code , m);
124             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
125         }
126         else if(left==1 && up==2){
127             if(i==enx && j==eny) {
128                 code[j-1] = code[j] = 0;
129                 if(j == m) shift(code , m);
130                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
131             }
132         }
133         else{
134             code[j-1]=code[j]=0;
135             if(j == m) shift(code , m);
136             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
137         }
138     }
139 }
140 
141 void dpblock(int i , int j , int cur)
142 {
143     int k , left , up;
144     for(k=0 ; k<hashmap[cur].size ; k++){
145         decode(code , m , hashmap[cur].state[k]);
146         left = code[j-1];
147         up = code[j];
148        // cout<<"block: "<<i<<" "<<j<<" "<<left<<" "<<up<<endl;
149         if(!left && !up){
150             if(j==m) shift(code , m);
151             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
152 
153         }
154     }
155 }
156 
157 void dpselect(int i , int j , int cur)
158 {
159     int k , left , up;
160     for(k=0 ; k<hashmap[cur].size ; k++){
161         decode(code , m , hashmap[cur].state[k]);
162         left = code[j-1];
163         up = code[j];
164         if(left==2 && !up){
165             code[j-1] = 0 , code[j] = 2;
166             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
167         }
168     }
169 }
170 
171 char s[MAXD][MAXD];
172 
173 void init()
174 {
175     for(int i=1 ; i<=n ; i++){
176         scanf("%s" , s[i]+1);
177         for(int j=1 ; j<=m ; j++){
178             mp[i][j] = s[i][j]=='.';
179         }
180     }
181     for(int i=n ; i>=1 ; i--)
182         for(int j=1 ; j<=m ; j++)
183             if(mp[i][j]) enx=i , eny=j;
184     mp[n+1][1] = 1 , mp[n+1][m] = 1;
185     for(int i=2 ; i<m ; i++) mp[n+1][i] = 2;
186     n++;
187     for(int i=1 ; i<=m+1 ; i++) mp[0][i] = 0;
188     for(int i=0 ; i<=n ; i++) mp[i][m+1] = 0;
189    /* for(int i=0 ; i<=n ; i++)
190     {
191         for(int j=1 ; j<=m+1 ; j++){
192             cout<<mp[i][j]<<" ";
193         }
194         cout<<endl;
195     }
196     cout<<enx<<" "<<eny<<endl;*/
197 }
198 
199 ll solve()
200 {
201     ans = 0;
202     int cur = 0;
203     hashmap[cur].init();
204     hashmap[cur].push_in(0 , 1);
205     for(int i=n ; i>=1 ; i--){
206         for(int j=1 ; j<=m ; j++){
207             hashmap[cur^1].init();
208             if(mp[i][j]==1) dpblank(i , j , cur);
209             else if(mp[i][j]==0) dpblock(i , j , cur);
210             else dpselect(i , j , cur);
211             cur^=1;
212         }
213 
214     }
215     for(int i=0 ; i<hashmap[cur].size ; i++) ans+=hashmap[cur].f[i];
216     return ans;
217 }
218 
219 int main()
220 {
221    // freopen("in.txt" , "r" , stdin);
222     int cas = 0;
223     while(scanf("%d%d" , &n , &m) , n+m)
224     {
225         init();
226        // printf("Case %d: ",++cas);
227         if(n==1 && m==1){
228             printf("%d\n" , 1);
229             continue;
230         }
231         printf("%I64d\n" , solve());
232     }
233     return 0;
234 }

 

 posted on 2015-08-15 10:20  Love风吟  阅读(264)  评论(0编辑  收藏  举报