【bzoj2331】[SCOI2011]地板

题目链接:

  TP

题解:

  分类讨论好烦啊!

  0表示没有插头,1、2表示有插头,1表示接下来可以转弯,2表示接下来不能转弯,只能停在一个地方。

  然后分类讨论:

插头状态 到达状态
0 0 2 2 | 1 0 | 0 1

0 1

0 2

0 2 | 1 0

0 0 | 0 2

1 0

2 0

与上列相反

1 1

0 0

  对于[0 2]的讨论容易想错,开始我想可以在下面会变成[1 0],然而发现WA了,仔细思考发现我想的在下面转弯完全可以在这里断掉,然后再开一个新的,我只要在意当前这个L型砖的走向即可。

代码:

  

  1 #define Troy
  2 
  3 #include <bits/stdc++.h>
  4 
  5 using namespace std;
  6 
  7 const int mod=20110520,
  8           N=2e5+5;
  9 
 10 int n,m,c,xx,yy,dp[2][N],tot[2],stk[2][N],h[N],bit[20],ans;
 11 
 12 char mp[101][101];
 13 
 14 inline void reversal(){
 15     char s[101][101];
 16     for(int i=1;i<=n;++i)   
 17         for(int j=1;j<=m;++j)
 18             s[j][i]=mp[i][j];
 19     memcpy(mp,s,sizeof(mp));
 20     swap(n,m);
 21 }
 22 
 23 inline void _plus(int &x,int y){
 24     x+=y;
 25     if(x>=mod)  x-=mod;
 26 }
 27 
 28 struct edges{
 29     int v;edges *last;
 30 }edge[N],*head[(int)4e4];int cnt;
 31 
 32 inline void  push(int s,int val){
 33     int pos=s%39973;
 34     for(edges *i=head[pos];i;i=i->last){
 35         if(stk[c][i->v]==s){
 36             (dp[c][i->v]+=val)%=mod;
 37             return ;
 38         }
 39     }
 40     // while(h[pos]!=-1){
 41     //     if(stk[t][h[pos]]==s){
 42     //         dp[t][h[pos]]+=val;
 43     //         return ;
 44     //     }
 45     //     ++pos;
 46     //     if(pos==N) pos=0;
 47     // }
 48     dp[c][++tot[c]]=val;   stk[c][tot[c]]=s;
 49     edge[++cnt]=(edges){tot[c],head[pos]};head[pos]=edge+cnt;
 50 }
 51 
 52 inline void DP(){
 53     dp[0][1]=1,tot[0]=1;
 54     register int i,j,k;
 55     for(i=1;i<=n;++i){
 56         for(j=1;j<=tot[c];++j)  stk[c][j]<<=2;
 57         for(j=1;j<=m;++j){
 58             c^=1;tot[c]=0;cnt=0;
 59             memset(head,0,sizeof(head));
 60             for(k=1;k<=tot[c^1];++k){
 61                 int s=stk[c^1][k],p=(s>>bit[j-1])&3,q=(s>>bit[j])&3;
 62                 int val=dp[c^1][k];
 63                 if(!mp[i][j]){
 64                     if(!p&&!q)  push(s,val);
 65                 }else   if(!p&&!q){
 66                     int x;
 67                     if(mp[i+1][j]){
 68                         x=s+(1<<bit[j-1]);
 69                         push(x,val);
 70                     }if(mp[i][j+1]){
 71                         x=s+(1<<bit[j]);
 72                         push(x,val);
 73                     }if(mp[i+1][j]&&mp[i][j+1]){
 74                         s+=(1<<bit[j-1])+(1<<bit[j])<<1;
 75                         push(s,val);
 76                     }
 77                 }else   if(!p){
 78                     if(q==1){
 79                         if(mp[i+1][j]){
 80                             push(s^(1<<bit[j-1]^(1<<bit[j])),val);
 81                         }
 82                         if(mp[i][j+1]){
 83                             push(s+(1<<bit[j]),val);
 84                         }
 85                     }else{
 86                         s^=q<<bit[j];
 87                         push(s,val);
 88                         if(mp[i+1][j])
 89                             push(s^(1<<bit[j-1]+1),val);
 90                     }
 91                 }else   if(!q){
 92                     if(p==1){
 93                         if(mp[i][j+1]){
 94                             push(s^(1<<bit[j-1]^(1<<bit[j])),val);
 95                         }
 96                         if(mp[i+1][j]){
 97                             push(s+(1<<bit[j-1]),val);
 98                         }
 99                     }else{
100                         s^=(1<<bit[j-1]+1);
101                         push(s,val);
102                         if(mp[i][j+1])
103                             push(s^(1<<bit[j]+1),val);
104                     }
105                 }else   if(p+q==2){
106                     s^=(1<<bit[j-1])+(1<<bit[j]);
107                     push(s,val);
108                 }
109             }
110         }  
111     }
112 }
113 
114 int main(){
115     scanf("%d%d",&n,&m);
116     for(int i=1;i<=n;++i)   scanf("%s",mp[i]+1);
117     for(int i=0;i<=15;++i)  bit[i]=i<<1;
118     if(n<m) reversal();
119     for(int i=1;i<=n;++i)   
120         for(int j=1;j<=m;++j)
121             if(mp[i][j]=='_')   mp[i][j]=1,xx=i,yy=j;
122             else    mp[i][j]=0;
123     DP();
124     printf("%d
",tot[c]?dp[c][1]:0);
125 }
原文地址:https://www.cnblogs.com/Troywar/p/7988445.html