【BZOJ】2331: [SCOI2011]地板

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2331


 

一眼插头DP...

考虑一个L形的东西,要构成它可以划分为两个阶段,即当前线段是拐了弯的还是没有拐弯的。
所以$4$进制表示,$0$表示没有插头,$1$表示插头指向拐点,$2$表示插头离开拐点。

转移:

令${(x,y)}$表示当前点左插头和上插头的形态。

${(0,0)}$------>${(0,1)}$,${(1,0)}$,${(2,2)}$

${(0,1)}$------>${(1,0)}$,${(0,2)}$

${(0,2)}$------>${(0,0)}$,${(2,0)}$

${(1,0)}$------>${(0,1)}$,${(2,0)}$

${(2,0)}$------>${(0,0)}$,${(0,2)}$

当然如果有障碍就不能走。


  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<cstring>
  8 using namespace std;
  9 #define maxn 10010
 10 #define llg long long 
 11 #define SIZE 10007
 12 #define md 20110520
 13 #define maxnZT (1<<21)
 14 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 15 llg n,m,code[maxn],zt[2][maxnZT],v[2][maxnZT],g[110][110],size[2],now,la;
 16 
 17 struct node
 18 {
 19     llg pos,x,val;
 20 };
 21 
 22 vector<node>a[2][SIZE];
 23 
 24 void outcode(llg x){for (llg i=0;i<=m;i++) code[i]=x&3,x>>=2;}
 25 
 26 void encode(llg p,llg val)
 27 {
 28     llg x=0;
 29     for (llg i=0;i<=m;i++) x+=code[i]*(1<<(i*2));
 30     llg wz=x%SIZE,E=a[p][wz].size();
 31     for (llg i=0;i<E;i++)
 32         if (a[p][wz][i].x==x)
 33         {
 34             a[p][wz][i].val+=val;  a[p][wz][i].val%=md;
 35             v[p][a[p][wz][i].pos]+=val; v[p][a[p][wz][i].pos]%=md;
 36             return ;
 37         }
 38     size[p]++;
 39     node NEW;
 40     NEW.pos=size[p],NEW.x=x,NEW.val=val;
 41     a[p][wz].push_back(NEW);
 42     zt[p][size[p]]=x; v[p][size[p]]=val;
 43 }
 44 
 45 void init()
 46 {
 47     cin>>n>>m;
 48     char ch;
 49     for (llg i=1;i<=n;i++)
 50         for (llg j=1;j<=m;j++)
 51         {
 52             ch=getchar();
 53             while (ch!='*' && ch!='_') ch=getchar();
 54             if (n<m) g[j][i]=(ch=='_');
 55             else g[i][j]=(ch=='_');
 56         }
 57     if (n<m) swap(n,m);
 58 }
 59 
 60 void init_a(llg p){for (llg i=0;i<SIZE;i++) a[p][i].clear(); size[p]=0;}
 61 
 62 void DP()
 63 {
 64     llg le,up,V;
 65     encode(0,1);
 66     for (llg i=1;i<=n;i++)
 67     {
 68         for (llg k=1;k<=size[now];k++) zt[now][k]*=4;//轮廓线左移一格
 69         for (llg j=1;j<=m;j++)
 70         {
 71             now^=1; la=now^1; size[now]=0;
 72             init_a(now);
 73             for (llg k=1;k<=size[la];k++)
 74             {
 75                 outcode(zt[la][k]);
 76                 le=code[j-1],up=code[j],V=v[la][k];//提取左插头和上插头
 77             
 78                 if (g[i][j]==0)
 79                 {
 80                     if (le==0 && up==0) encode(now,V);
 81                     continue;
 82                 }
 83 
 84                 if (!le && !up)
 85                 {
 86                     if (j<m && g[i][j+1]==1)
 87                     {
 88                         code[j-1]=0,code[j]=1;
 89                         encode(now,V);
 90                         if (g[i+1][j]==1)
 91                         {
 92                             code[j-1]=code[j]=2;
 93                             encode(now,V);
 94                         }
 95                     }
 96                     if (g[i+1][j]==1)
 97                     {
 98                         code[j-1]=1,code[j]=0;
 99                         encode(now,V);
100                     }
101                     continue;
102                 }
103 
104                 if (le && up)
105                 {
106                     if (le==1 && up==1)
107                     {
108                         code[j-1]=code[j]=0;
109                         encode(now,V);
110                     }
111                     continue;
112                 }
113                 
114                 if (le==1 && up==0)
115                 {
116                     if (g[i+1][j]==1)
117                     {
118                         code[j-1]=2;
119                         encode(now,V);
120                     }
121                     if (g[i][j+1]==1 && j<m)
122                     {
123                         code[j]=1; code[j-1]=0;
124                         encode(now,V);
125                     }
126                     continue;
127                 }
128 
129                 if (le==2 && up==0)
130                 {
131                     if (j<m && g[i][j+1]==1)
132                     {
133                         code[j]=2; code[j-1]=0;
134                         encode(now,V);
135                     }
136                     code[j]=code[j-1]=0;
137                     encode(now,V);
138                     continue;
139                 }
140 
141                 if (le==0 && up==1)
142                 {
143                     if (g[i+1][j]==1)
144                         {
145                             code[j-1]=1,code[j]=0;
146                             encode(now,V);
147                         }
148                     if (j<m && g[i][j+1]==1)
149                     {
150                         code[j-1]=0; code[j]=2;
151                         encode(now,V);
152                     }
153                     continue;
154                 }
155                 
156                 if (le==0 && up==2)
157                 {
158                     if (g[i+1][j]==1)
159                     {
160                         code[j]=0,code[j-1]=2;
161                         encode(now,V);
162                     }
163                     code[j-1]=code[j]=0;
164                     encode(now,V);
165                     continue;
166                 }
167             }
168         }
169     }
170 }
171 
172 int main()
173 {
174     yyj("BZOJ2331");
175     init();
176     DP();
177     llg ans=0;
178     bool pd;
179     for (llg i=1;i<=size[now];i++)
180     {
181         outcode(zt[now][i]);
182         pd=true;
183         for (llg j=0;j<=m;j++) if (code[j]) pd=false;
184         if (pd) ans+=v[now][i];
185     }
186     cout<<ans%md;
187     return 0;
188 }

 

posted @ 2017-03-02 17:58  №〓→龙光←  阅读(277)  评论(0编辑  收藏  举报