BZOJ2331 [SCOI2011]地板
Submit: 1104 Solved: 468
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
插头DP
状态转移还是看代码吧233
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #define LL long long 9 using namespace std; 10 const int p=100007; 11 const int mod=20110520; 12 const int mxn=2000100; 13 int now,pre; 14 struct edge{ 15 int v,nxt,id; 16 }e[2][mxn]; 17 int hd[2][mxn],mct[2]={0}; 18 LL f[2][mxn]; 19 void add(int v,LL w){//hash 20 int z=v%p; 21 for(int i=hd[now][z];i;i=e[now][i].nxt){ 22 if(e[now][i].v==v){ 23 f[now][i]=(f[now][i]+w)%mod; 24 return; 25 } 26 } 27 e[now][++mct[now]]=(edge){v,hd[now][z],z};hd[now][z]=mct[now]; 28 f[now][mct[now]]=w; 29 return; 30 } 31 int n,m; 32 char mp[125][125]; 33 char tmp[125][125]; 34 int b[25]; 35 int main(){ 36 int i,j; 37 for(i=1;i<=20;i++)b[i]=i<<1; 38 // 39 scanf("%d%d",&n,&m); 40 for(i=1;i<=n;i++) 41 scanf("%s",mp[i]+1); 42 if(n<m){ 43 for(i=1;i<=n;i++) 44 for(j=1;j<=m;j++) 45 tmp[j][i]=mp[i][j]; 46 swap(n,m); 47 memcpy(mp,tmp,sizeof tmp); 48 } 49 /* 50 //test 51 for(i=1;i<=n;i++){ 52 for(j=1;j<=m;j++){ 53 printf("%c ",mp[i][j]); 54 } 55 printf("\n"); 56 } 57 */ 58 memset(f,0,sizeof f); 59 now=0;pre=1; 60 add(0,1); 61 for(i=1;i<=n;i++){//行 62 for(j=1;j<=mct[now];j++) e[now][j].v<<=2;//整体左移 63 for(j=1;j<=m;j++){//列 64 swap(now,pre); 65 for(int k=1;k<=mct[now];k++)hd[now][e[now][k].id]=0; 66 mct[now]=0; 67 //clear 68 for(int k=1;k<=mct[pre];k++){ 69 int v=e[pre][k].v; 70 int x=v>>b[j-1]&3;//提取左一位 71 int y=v>>b[j]&3;//提取当前位 72 LL w=f[pre][k]; 73 if(mp[i][j]=='*'){if(!(x|y))add(v,w);}//柱子 74 //以下为地板情况 75 else if(x==1 && y==1){ // 11->00 76 add(v^(1<<b[j])^(1<<b[j-1]),w); 77 } 78 else if(x+y==0){ // 79 if(mp[i+1][j]=='_')add(v^(1<<b[j-1]),w); 80 if(mp[i][j+1]=='_')add(v^(1<<b[j]),w); 81 if(mp[i+1][j]=='_' && mp[i][j+1]=='_')add(v^(2<<b[j-1])^(2<<b[j]),w); 82 } 83 else if(x==1 && !y){ //10 -> 20 01 84 if(mp[i+1][j]=='_')add(v+(1<<b[j-1]),w); 85 if(mp[i][j+1]=='_')add(v^(1<<b[j-1])^(1<<b[j]),w); 86 } 87 else if(!x && y==1){ //01 -> 10 02 88 if(mp[i+1][j]=='_')add(v^(1<<b[j-1])^(1<<b[j]),w); 89 if(mp[i][j+1]=='_')add(v+(1<<b[j]),w); 90 } 91 else if(x==2 && !y){ //20 -> 00 02 92 add(v^(2<<b[j-1]),w); 93 if(mp[i][j+1]=='_')add(v^(2<<b[j-1])^(2<<b[j]),w); 94 } 95 else if(!x && y==2){ //02 -> 00 20 96 add(v^(2<<b[j]),w); 97 if(mp[i+1][j]=='_')add(v^(2<<b[j-1])^(2<<b[j]),w); 98 } 99 } 100 } 101 } 102 if(mct[now])printf("%lld\n",f[now][1]); 103 else printf("0\n"); 104 return 0; 105 }
本文为博主原创文章,转载请注明出处。