POJ 1739

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

题目大意:

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

这里不是求回路,但是我们可以考虑,在最下面一行再增加一行,那么就可以当做求此时左下角到右下角的回路总数,那么就转化成了陈丹琦论文的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 }
时间: 2024-10-29 18:33:50

POJ 1739的相关文章

POJ 1739:Tony&#39;s Tour

Description A square township has been divided up into n*m(n rows and m columns) square plots (1<=N,M<=8),some of them are blocked, others are unblocked. The Farm is located in the lower left plot and the Market is located in the lower right plot. T

【POJ 1739】Tony&#39;s Tour

Tony's Tour Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3545   Accepted: 1653 Description A square township has been divided up into n*m(n rows and m columns) square plots (1<=N,M<=8),some of them are blocked, others are unblocked.

【插头DP】 POJ 1739 Tony&#39;s Tour

通道:http://poj.org/problem?id=1739 题意:左下角走到右下角路径数,单回路.做法就是我们新添2行后寻找回路就可以啦 . 代码: 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 =

poj 1739 Tony&#39;s Tour 插头dp模板题

题意: 给一个迷宫,求左下角到右下角的路径数. 分析: 插头dp的模板题,建议先看cdq的论文再看代码,这份代码在模板基础上略微有改动.论文地址http://wenku.baidu.com/view/ed2b3e23482fb4daa58d4b74.html 代码: #include <iostream> using namespace std; const int maxD=16; const int HASH=10007; const int STATE=1000024; int N,M;

【POJ】【1739】Tony&#39;s Tour

插头DP 楼教主男人八题之一! 要求从左下角走到右下角的哈密顿路径数量. 啊嘞,我只会求哈密顿回路啊……这可怎么搞…… 容易想到:要是把起点和重点直接连上就变成一条回路了……那么我们就连一下~ 我们可以在整张图下面加两行:(例:3*5) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 红色的是原来的起点和终点,下面紫色的路径将这两个点连了起来= =然后这题瞬间就变回了Formula 1那题……求哈密顿回路数量,so easy有没有~(其实不这样

补题清单

HDU 3585 HDU 1693 URAL 1519 FZU 1977 HDU 1964 HDU 3377 POJ 1739 POJ 3133 BZOJ 1025 HDU 4285 专题7 1003 1004 1005 1006 1008

插头与轮廓线与基于连通性状态压缩的动态规划

问题定义 什么是插头DP 在一个n*m的棋盘上(n与m很小),求: 有多少种不同的回路数 用1条回路经过所有点的方案数 用1条回路经过部分点的方案数 1条路径上的权值和最大 的这一类问题,通常可以用插头DP来解决. 这类问题通常很明显,但代码量大又容易出错,有时TLE有时MLE. 什么是基于状态压缩的动态规划 基于状态压缩的动态规划问题是一类以集合信息为状态且状态总数为指数级的特殊的动态规划问题. 在状态压缩的基础上,有一类问题的状态中必须要记录若干个元素的连通情况,我们称这样的问题为基于连通性

插头DP小结

首先是CDQ<基于连通性状态压缩的动态规划问题>论文上的题目: URAL 1519 Formula 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int maxn = 15; 6 const int HASH = 30007; 7 const int SIZE = 1000010; 8 typedef long lon

【HDOJ】【2829】Lawrence

DP/四边形不等式 做过POJ 1739 邮局那道题后就很容易写出动规方程: dp[i][j]=min{dp[i-1][k]+w[k+1][j]}(表示前 j 个点分成 i 块的最小代价) $w(l,r)=\sum_{i=l}^{r}\sum_{j=i+1}^{r}a[i]*a[j]$ 那么就有 $w(l,r+1)=w(l,r)+a[j]*\sum\limits_{i=l}^{r}a[i]$ 所以:w[i][j]明显满足 关于区间包含的单调性 然后我们大胆猜想,小(bu)心(yong)证明,w[