BZOJ2331: [SCOI2011]地板

$n*m \leq 100$的地板,问在空地铺$L$型砖的方案数。空地一定要铺,非空地一定不铺。对某个数取模。

直接插头DP。插头分三类,空,没拐弯,有拐弯。转移慢慢分。

  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 //#include<time.h>
  5 //#include<complex>
  6 #include<algorithm>
  7 #include<stdlib.h>
  8 using namespace std;
  9 
 10 #define LL long long
 11 int qread()
 12 {
 13     char c; int s=0; while ((c=getchar())<'0' || c>'9');
 14     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s;
 15 }
 16 
 17 //Pay attention to '-' and LL of qread!!!!
 18 
 19 int n,m;
 20 const int mod=20110520;
 21 bool mp[111][111];
 22 
 23 #define maxn 1000007
 24 int first[maxn],Next[maxn],ans[2][maxn],cur,state[2][maxn],len[2];
 25 void insert(int s,int v)
 26 {
 27     int h=s%maxn,y=cur^1;
 28     for (int i=first[h];i;i=Next[i]) if (state[y][i]==s)
 29     {ans[y][i]+=v; ans[y][i]-=ans[y][i]>=mod?mod:0; return;}
 30     state[y][++len[y]]=s; ans[y][len[y]]=v;
 31     Next[len[y]]=first[h]; first[h]=len[y];
 32 }
 33 
 34 int main()
 35 {
 36     scanf("%d%d",&n,&m);
 37     if (n<m)
 38     {
 39         for (int i=1;i<=n;i++)
 40             for (int j=1;j<=m;j++)
 41             {
 42                 char c; while ((c=getchar())!='*' && c!='_');
 43                 mp[j][i]=(c=='*');
 44             }
 45         n^=m^=n^=m;
 46     }
 47     else
 48     {
 49         for (int i=1;i<=n;i++)
 50             for (int j=1;j<=m;j++)    
 51             {
 52                 char c; while ((c=getchar())!='*' && c!='_');
 53                 mp[i][j]=(c=='*');
 54             }
 55     }
 56     
 57     cur=1; insert(0,1); cur=0;
 58     for (int i=1;i<=n;i++)
 59         for (int j=1;j<=m;j++)
 60         {
 61             for (int k=1;k<=len[cur];k++) first[state[cur][k]%maxn]=0;
 62             for (int k=1;k<=len[cur];k++)
 63             {
 64                 int now=state[cur][k],p=now&3,q=(now>>2)&3,nk;
 65                 if (mp[i][j]==1) {if (p==0 && q==0) {nk=now>>2; insert(nk,ans[cur][k]);}}
 66                 else if (p==0 && q==0)
 67                 {
 68                     nk=(now>>2)|(1<<(m<<1)); insert(nk,ans[cur][k]);
 69                     if (j<m)
 70                     {
 71                         nk=(now>>2)|1; insert(nk,ans[cur][k]);
 72                         nk=(now>>2)|2|(2<<(m<<1)); insert(nk,ans[cur][k]);
 73                     }
 74                 }
 75                 else if (p==1 && q==0)
 76                 {
 77                     nk=(now>>2)|(2<<(m<<1)); insert(nk,ans[cur][k]);
 78                     if (j<m) {nk=(now>>2)|1; insert(nk,ans[cur][k]);}
 79                 }
 80                 else if (p==2 && q==0)
 81                 {
 82                     nk=(now>>2); insert(nk,ans[cur][k]);
 83                     if (j<m) {nk=(now>>2)|2; insert(nk,ans[cur][k]);}
 84                 }
 85                 else if (p==0 && q==1)
 86                 {
 87                     nk=((now>>2)^q)|(1<<(m<<1)); insert(nk,ans[cur][k]);
 88                     if (j<m) {nk=((now>>2)^q)|2; insert(nk,ans[cur][k]);}
 89                 }
 90                 else if (p==0 && q==2)
 91                 {
 92                     nk=((now>>2)^q)|(2<<(m<<1)); insert(nk,ans[cur][k]);
 93                     nk=(now>>2)^q; insert(nk,ans[cur][k]);
 94                 }
 95                 else if (p==1 && q==1) {nk=(now>>2)^q; insert(nk,ans[cur][k]);}
 96             }
 97             len[cur]=0; cur^=1;
 98         }
 99     
100     int Ans=0;
101     for (int i=1;i<=len[cur];i++) if (state[cur][i]==0) {Ans=ans[cur][i]; break;}
102     printf("%d\n",Ans);
103     return 0;
104 }
View Code

 

posted @ 2018-04-16 16:13  Blue233333  阅读(160)  评论(0编辑  收藏  举报