【bzoj2331】[SCOI2011]地板

时间:2021-03-12 17:46:18

题目链接:

  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型砖的走向即可。

代码:

  

 #define Troy

 #include <bits/stdc++.h>

 using namespace std;

 const int mod=,
N=2e5+; int n,m,c,xx,yy,dp[][N],tot[],stk[][N],h[N],bit[],ans; char mp[][]; inline void reversal(){
char s[][];
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
s[j][i]=mp[i][j];
memcpy(mp,s,sizeof(mp));
swap(n,m);
} inline void _plus(int &x,int y){
x+=y;
if(x>=mod) x-=mod;
} struct edges{
int v;edges *last;
}edge[N],*head[(int)4e4];int cnt; inline void push(int s,int val){
int pos=s%;
for(edges *i=head[pos];i;i=i->last){
if(stk[c][i->v]==s){
(dp[c][i->v]+=val)%=mod;
return ;
}
}
// while(h[pos]!=-1){
// if(stk[t][h[pos]]==s){
// dp[t][h[pos]]+=val;
// return ;
// }
// ++pos;
// if(pos==N) pos=0;
// }
dp[c][++tot[c]]=val; stk[c][tot[c]]=s;
edge[++cnt]=(edges){tot[c],head[pos]};head[pos]=edge+cnt;
} inline void DP(){
dp[][]=,tot[]=;
register int i,j,k;
for(i=;i<=n;++i){
for(j=;j<=tot[c];++j) stk[c][j]<<=;
for(j=;j<=m;++j){
c^=;tot[c]=;cnt=;
memset(head,,sizeof(head));
for(k=;k<=tot[c^];++k){
int s=stk[c^][k],p=(s>>bit[j-])&,q=(s>>bit[j])&;
int val=dp[c^][k];
if(!mp[i][j]){
if(!p&&!q) push(s,val);
}else if(!p&&!q){
int x;
if(mp[i+][j]){
x=s+(<<bit[j-]);
push(x,val);
}if(mp[i][j+]){
x=s+(<<bit[j]);
push(x,val);
}if(mp[i+][j]&&mp[i][j+]){
s+=(<<bit[j-])+(<<bit[j])<<;
push(s,val);
}
}else if(!p){
if(q==){
if(mp[i+][j]){
push(s^(<<bit[j-]^(<<bit[j])),val);
}
if(mp[i][j+]){
push(s+(<<bit[j]),val);
}
}else{
s^=q<<bit[j];
push(s,val);
if(mp[i+][j])
push(s^(<<bit[j-]+),val);
}
}else if(!q){
if(p==){
if(mp[i][j+]){
push(s^(<<bit[j-]^(<<bit[j])),val);
}
if(mp[i+][j]){
push(s+(<<bit[j-]),val);
}
}else{
s^=(<<bit[j-]+);
push(s,val);
if(mp[i][j+])
push(s^(<<bit[j]+),val);
}
}else if(p+q==){
s^=(<<bit[j-])+(<<bit[j]);
push(s,val);
}
}
}
}
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i) scanf("%s",mp[i]+);
for(int i=;i<=;++i) bit[i]=i<<;
if(n<m) reversal();
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
if(mp[i][j]=='_') mp[i][j]=,xx=i,yy=j;
else mp[i][j]=;
DP();
printf("%d\n",tot[c]?dp[c][]:);
}