【bzoj2331】[SCOI2011]地板
题目链接:
题解:
分类讨论好烦啊!
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\n",tot[c]?dp[c][1]:0); 125 }
没有什么不可能。