bzoj:2331: [SCOI2011]地板
Description
lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?
需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。
Input
输入的第一行包含两个整数,R和C,表示客厅的大小。
接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。
Output
输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。
Sample Input
2 2
*_
__
*_
__
Sample Output
1
插头dp……蒟蒻的模板慢得要死……用0表示无插头,1表示有未拐的插头,2表示已拐的插头……
然后转移就自己YY一下就好了……
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=20110520; const int MAXN=177147; int i; struct na{ int x,z; na(int xx,int zz):x(xx),z(zz){} }; int n,m,x,y,z,a[21],k,p1,p2,en,t; bool map[101][101]; int f[2][MAXN+1],ans=0; int v[2][MAXN+1]; queue <na> q; inline int gx(int x,int q1,int q2){k=0;for (register int i=m+1;i;i--) k=k*3+(i==x?q1:(i==x+1?q2:a[i]));return k;} inline void up(int r,int z,int lj){ if (r==en){ ans+=lj; if (ans>=INF) ans-=INF; return; } r++; k=r%2; if (v[k][z]!=r) v[k][z]=r,f[k][z]=0,q.push(na(r,z)); f[k][z]+=lj;if (f[k][z]>=INF) f[k][z]-=INF; } char c[101]; int main(){ register int i,j,p; scanf("%d%d",&n,&m); if (n<m){ swap(n,m); for (j=1;j<=m;j++){ scanf("%s",c); for (i=1;i<=n;i++) map[j][i]=c[i-1]=='_'; } }else{ for (j=1;j<=n;j++){ scanf("%s",c); for (i=1;i<=m;i++) map[i][j]=c[i-1]=='_'; } } en=n*m-1; while(!map[en%m+1][en/m+1]) en--; f[0][0]=v[0][0]=1; q.push(na(0,0)); while(!q.empty()){ na no=q.front();q.pop(); int an=f[no.x%2][no.z]; if(no.x%m==0) no.z*=3; x=no.x%m+1;y=no.x/m+1; for (i=1;i<=m+1;i++) a[i]=0; for (i=1,j=no.z;j;i++,j/=3) a[i]=j%3; if (!map[x][y]) up(no.x,gx(100,0,0),an);else if (a[x]==1&&a[x+1]==1) up(no.x,gx(x,0,0),an);else if (a[x]==0&&a[x+1]==0){ if (map[x+1][y]) up(no.x,gx(x,0,1),an); if (map[x][y+1]) up(no.x,gx(x,1,0),an); if (map[x][y+1]&&map[x+1][y]) up(no.x,gx(x,2,2),an); }else if (a[x]==0){ if (map[x][y+1]) up(no.x,gx(x,a[x+1],0),an); if (map[x+1][y]&&a[x+1]==1) up(no.x,gx(x,0,2),an); if (a[x+1]==2) up(no.x,gx(x,0,0),an); }else if (a[x+1]==0){ if (map[x+1][y]) up(no.x,gx(x,0,a[x]),an); if (map[x][y+1]&&a[x]==1) up(no.x,gx(x,2,0),an); if (a[x]==2) up(no.x,gx(x,0,0),an); } } printf("%d\n",ans); }