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 }