bzoj 2331 [SCOI2011]地板 插头dp
2331: [SCOI2011]地板
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1436 Solved: 606
[Submit][Status][Discuss]
Description
lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?
需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。
Input
输入的第一行包含两个整数,R和C,表示客厅的大小。
接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。
Output
输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。
Sample Input
2 2
*_
__
*_
__
Sample Output
1
HINT
R*C<=100
Source
题解,因为每个位置都需要铺满,那么而且只有L型插头,
所以有三种类型
0表示没有插头,1表示插头还没有拐过弯,2表示插头已经拐过弯了。
然后分析合并的状态,用hash的方法去记录状态,不然如果运用位运算的话,
空间存不下,用hash的方式,这样在CDQ的论文中有讲到,这样的方法比较优秀的,
1.00-->22 或 10 或 01
2.11-->00
3.10-->20 或 01
20-->00 或 02
4.01-->10 或 02
02-->00 或 20
1 #pragma GCC optimize(2) 2 #pragma G++ optimize(2) 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstdio> 7 #include<cstring> 8 9 #define N 107 10 #define M 200007 11 #define mod 20110520 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 17 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 21 int n,m,now,pre,cnt; 22 int a[N][N],f[2][M],tot[2],hash[2][M]; 23 int hed[M],nxt[M],v[M],bit[N]; 24 char s[N]; 25 26 void ins(int sta,int shu) 27 { 28 int x=sta%50000; 29 for (int i=hed[x];i;i=nxt[i]) 30 if(hash[now][v[i]]==sta) 31 { 32 (f[now][v[i]]+=shu)%=mod; 33 return; 34 } 35 tot[now]++; 36 hash[now][tot[now]]=sta; 37 f[now][tot[now]]=shu; 38 cnt++,v[cnt]=tot[now],nxt[cnt]=hed[x],hed[x]=cnt; 39 } 40 void solve() 41 { 42 now=1,pre=0; 43 tot[now]=1; 44 hash[now][1]=0,f[now][1]=1; 45 for (int i=1;i<=n;i++) 46 { 47 for (int j=1;j<=tot[now];j++)hash[now][j]<<=2; 48 for (int j=1;j<=m;j++) 49 { 50 swap(now,pre),tot[now]=0; 51 cnt=0; 52 memset(f[now],0,sizeof(f[now])); 53 memset(hed,0,sizeof(hed)); 54 for (int k=1;k<=tot[pre];k++) 55 { 56 int sta=hash[pre][k],num=f[pre][k]; 57 if(!num)continue; 58 int x=(sta/(1<<bit[j-1]))%4,y=(sta/(1<<bit[j]))%4; 59 if(!a[i][j]) 60 { 61 if(!x&&!y)ins(sta,num); 62 } 63 else if(!x&&!y) 64 { 65 if(a[i+1][j])ins(sta+(1<<bit[j-1]),num); 66 if(a[i][j+1])ins(sta+(1<<bit[j]),num); 67 if(a[i+1][j]&&a[i][j+1])ins(sta+(1<<bit[j-1]+1)+(1<<(bit[j]+1)),num); 68 } 69 else if(!x) 70 { 71 if(y==1) 72 { 73 sta-=(1<<bit[j]); 74 if(a[i][j+1])ins(sta+(1<<bit[j]+1),num); 75 if(a[i+1][j])ins(sta+(1<<bit[j-1]),num); 76 } 77 else 78 { 79 sta-=(1<<bit[j]+1); 80 ins(sta,num); 81 if(a[i+1][j])ins(sta+(1<<bit[j-1]+1),num); 82 } 83 } 84 else if(!y) 85 { 86 if(x==1) 87 { 88 sta-=(1<<bit[j-1]); 89 if(a[i][j+1])ins(sta+(1<<bit[j]),num); 90 if(a[i+1][j])ins(sta+(1<<bit[j-1]+1),num); 91 } 92 else 93 { 94 sta-=(1<<bit[j-1]+1); 95 ins(sta,num); 96 if(a[i][j+1])ins(sta+(1<<bit[j]+1),num); 97 } 98 } 99 else if(x==1&&y==1) 100 { 101 sta-=(1<<bit[j-1])+(1<<bit[j]); 102 ins(sta,num); 103 } 104 } 105 } 106 } 107 } 108 int main() 109 { 110 for (int i=0;i<=100;i++)bit[i]=i<<1; 111 n=read(),m=read(); 112 if(n>=m) 113 { 114 for (int i=1;i<=n;i++) 115 { 116 scanf("%s",s+1); 117 for (int j=1;j<=m;j++) 118 if(s[j]=='_')a[i][j]=1; 119 else a[i][j]=0; 120 } 121 } 122 else 123 { 124 for (int i=1;i<=n;i++) 125 { 126 scanf("%s",s+1); 127 for (int j=1;j<=m;j++) 128 if(s[j]=='_')a[j][i]=1; 129 else a[j][i]=0; 130 } 131 swap(n,m); 132 } 133 solve(); 134 printf("%d\n",f[now][1]); 135 }