Description
lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?
需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。
Input
输入的第一行包含两个整数,R和C,表示客厅的大小。
接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。
Output
输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。
题解:
插头DP,0表示无插头,1表示有插头没有拐弯,2表示有插头且已经拐弯,分类讨论一下即可。但本题时限较紧(只有我这种蒟蒻才会这么觉得吧),原来我的模板Hash速度太慢,所以改了下模板,采用邻接表,速度快了不少。还有坑点是
R∗C<=100
,有可能出现像
3100
这么大的状态,所以这时要交换
R
、
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
const int mod=100037;
const LL Mod=20110520;
const int maxn=105;
struct Edge{int y,next;}e[210000];
int now=0,r,c,map[maxn][maxn],xx,yy,last[mod+10],len=0;
int list[2][mod*10],num[2];
LL ans=0,state[2][mod*10];
LL get(int s,int p)
{return (s>>((p-1)*2))&3;}
void change(int &s,int p,int v)
{
s^=get(s,p)<<((p-1)*2);
s^=(v)<<((p-1)*2);
}
void add(int st,LL sum)
{
int x=st%mod;
for(int i=last[x];i;i=e[i].next)
if(list[now][e[i].y]==st)
{
state[now][e[i].y]+=sum;
state[now][e[i].y]%=Mod;
return;
}
num[now]++;
list[now][num[now]]=st;
state[now][num[now]]=sum;
int t=++len;
e[t].y=num[now],e[t].next=last[x],last[x]=t;
}
void work()
{
state[0][1]=1;num[0]=1;list[0][1]=0;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
now^=1;
memset(last,0,sizeof(last));
num[now]=len=0;
for(int k=1;k<=num[now^1];k++)
{
int st=list[now^1][k];
LL sum=state[now^1][k];
int p=get(st,j),q=get(st,j+1);
if(i==xx&&j==yy)
{
if((p==1&&q==1)||(!p&&q==2)||(p==2&&!q))
ans+=sum,ans%=Mod;
continue;
}
if(!map[i][j])
{
if(!p&&!q)add(st,sum);
continue;
}
if(!p&&!q)
{
int st2=st;
if(map[i+1][j])change(st2,j,1),add(st2,sum);
st2=st;
if(map[i][j+1])change(st2,j+1,1),add(st2,sum);
st2=st;
if(map[i][j+1]&&map[i+1][j])
change(st2,j,2),change(st2,j+1,2),add(st2,sum);
}
else if(!p&&q)
{
int st2=st;
if(q==1)
{
if(map[i][j+1])change(st2,j+1,2),add(st2,sum);
st2=st;
if(map[i+1][j])change(st2,j,1),change(st2,j+1,0),add(st2,sum);
}
else
{
if(map[i+1][j])change(st2,j,2),change(st2,j+1,0),add(st2,sum);
st2=st;
change(st2,j+1,0);add(st2,sum);
}
}
else if(p&&!q)
{
int st2=st;
if(p==1)
{
if(map[i][j+1])change(st2,j+1,1),change(st2,j,0),add(st2,sum);
st2=st;
if(map[i+1][j])change(st2,j,2),add(st2,sum);
}
else
{
if(map[i][j+1])change(st2,j,0),change(st2,j+1,2),add(st2,sum);
st2=st;
change(st2,j,0);add(st2,sum);
}
}
else if(p==1&&q==1)
{
change(st,j,0);change(st,j+1,0);
add(st,sum);
}
}
}
for(int k=1;k<=num[now];k++)
list[now][k]<<=2;
}
}
int main()
{
memset(map,0,sizeof(map));
scanf("%d%d",&r,&c);
for(int i=1;i<=r;i++)
{
char str[110];
scanf("%s",str+1);
for(int j=1;j<=c;j++)
{
if(str[j]=='_')
{
if(r<c)map[j][i]=1,xx=j,yy=i;
else map[i][j]=1,xx=i,yy=j;
}
}
}
if(r<c)swap(r,c);
work();
printf("%lld",ans);
}