题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=1814
题解
插头dp,枚举边界线的插头,分类讨论转移点上插头和左插头的情况,来转移这个点的插头。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn=20;
const int hash_mod=1007;
const int maxd=maxn*maxn;
const int maxk=50000;
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
struct func
{
int x;
long long y;
};
struct hash_table
{
int now[hash_mod+10],pre[maxk+2],cnt;
func val[maxk+2];
int clear()
{
cnt=0;
memset(now,0,sizeof now);
return 0;
}
long long add(int s,long long v)
{
int trans=s%hash_mod,j=now[trans];
while(j)
{
if(val[j].x==s)
{
val[j].y+=v;
return val[j].y;
}
j=pre[j];
}
val[++cnt].x=s;
val[cnt].y=v;
pre[cnt]=now[trans];
now[trans]=cnt;
return v;
}
func get(int x)
{
return val[x];
}
};
hash_table ht[2];
int n,m,rv[maxn+4],v[maxn+2][maxd+2],now,last;
char s[maxn+4];
int decode(int x)
{
for(int i=0; i<=m; ++i)
{
rv[i]=x&3;
x>>=2;
}
return 0;
}
int encode()
{
int res=0;
for(int i=m; ~i; --i)
{
res=(res<<2)+rv[i];
}
return res;
}
int findl(int pos)
{
int now=-1;
while(1)
{
if(rv[pos])
{
now+=(rv[pos]==1)?1:-1;
}
if(!now)
{
return pos;
}
--pos;
}
}
int findr(int pos)
{
int now=1;
while(1)
{
if(rv[pos])
{
now+=(rv[pos]==1)?1:-1;
}
if(!now)
{
return pos;
}
++pos;
}
}
int expand(int x,int y,func from)
{
decode(from.x);
int west=rv[m],north=rv[y];
if((!y)&&west)
{
return 0;
}
if(v[x][y])
{
if(west||north)
{
return 0;
}
ht[now].add(encode(),from.y);
}
else if(west&&north)
{
rv[m]=rv[y]=0;
if(west<north)
{
int flag=0;
for(int i=0; i<=m; ++i)
{
if(rv[i])
{
flag=1;
break;
}
}
if(!((!flag)&&(x==n)))
{
return 0;
}
}
if(west==north)
{
if(west==1)
{
rv[findr(y+1)]=1;
}
else
{
rv[findl(y-1)]=2;
}
}
ht[now].add(encode(),from.y);
}
else if((!west)&&(!north))
{
rv[y]=1;
rv[m]=2;
ht[now].add(encode(),from.y);
}
else if((!west)&&north)
{
ht[now].add(encode(),from.y);
rv[m]=north;
rv[y]=0;
ht[now].add(encode(),from.y);
}
else if(west&&(!north))
{
ht[now].add(encode(),from.y);
rv[y]=west;
rv[m]=0;
ht[now].add(encode(),from.y);
}
return 0;
}
int work()
{
now=0;
last=1;
ht[0].clear();
ht[0].add(0,1);
for(int i=1; i<=n; ++i)
{
for(int j=0; j<m; ++j)
{
std::swap(now,last);
ht[now].clear();
for(int k=1; k<=ht[last].cnt; ++k)
{
expand(i,j,ht[last].get(k));
}
}
}
return 0;
}
int main()
{
n=read();
m=read();
for(int i=1; i<=n; ++i)
{
scanf("%s",s);
for(int j=0; j<m; ++j)
{
if(s[j]=='*')
{
v[i][j]=1;
}
}
}
work();
printf("%lld\n",ht[now].add(0,0));
return 0;
}