bzoj 2331 [SCOI2011]地板 插头dp

2331: [SCOI2011]地板

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 1436  Solved: 606
[Submit][Status][Discuss]

Description

 

lxhgww的小名叫L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?

需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。

 

Input

输入的第一行包含两个整数,RC,表示客厅的大小。

接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。

Output

输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。

Sample Input

2 2

*_

__

Sample Output

1

HINT

R*C<=100

Source

Day1

 

题解,因为每个位置都需要铺满,那么而且只有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 }

 

 

 

posted @ 2018-03-01 08:57  Kaiser-  阅读(163)  评论(0编辑  收藏  举报