P3272 [SCOI2011]地板
很巧妙的改变状态
\(0\)代表无插头,\(1\)代表有插头,且这个\("L"\)还未拐弯,\(2\)代表有插头,且这个\("L"\)已经拐过弯了
具体转移可以手推,用四进制即可
点击查看代码
#include<bits/stdc++.h>
#include<unordered_map>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 105
#define M 500007
#define mod 20110520
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,ex,ey,ans;
int g[N][N],gn[N][N];
unordered_map<int,int> f[2];
inline int Read()
{
char ch=getchar();bool f=0;int x=0;
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=1;
for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
if(f==1)x=-x;return x;
}
int Get_s(int num,int pos){return (num<<(pos<<1));}
int Ctdp()
{
int now=0;
int mxn=(1<<((m+1)<<1))-1;
f[now][0]=1;
f[now^1].clear();
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
int nxt=now^1;
for(auto k:f[now])
{
int S=k.first,val=k.second%mod;
int ctl=(S>>((j-1)<<1))&3,ctr=(S>>(j<<1))&3;
if(!g[i][j])
{
if(!ctl&&!ctr)
f[nxt][S]+=val;
continue;
}
if(!ctl&&!ctr)
{
if(g[i+1][j])
f[nxt][S^Get_s(1,j-1)]+=val;
if(g[i][j+1])
f[nxt][S^Get_s(1,j)]+=val;
if(g[i+1][j]&&g[i][j+1])
f[nxt][S^Get_s(2,j-1)^Get_s(2,j)]+=val;
continue;
}
if(!ctl&&ctr)
{
if(ctr==1)
{
if(g[i+1][j])
f[nxt][S^Get_s(1,j-1)^Get_s(1,j)]+=val;
if(g[i][j+1])
f[nxt][S^Get_s(1,j)^Get_s(2,j)]+=val;
}
if(ctr==2)
{
if(i==ex&&j==ey)
ans+=val,ans%=mod;
if(g[i+1][j])
f[nxt][S^Get_s(2,j)^Get_s(2,j-1)]+=val;
f[nxt][S^Get_s(2,j)]+=val;
}
continue;
}
if(ctl&&!ctr)
{
if(ctl==1)
{
if(g[i+1][j])
f[nxt][S^Get_s(1,j-1)^Get_s(2,j-1)]+=val;
if(g[i][j+1])
f[nxt][S^Get_s(1,j-1)^Get_s(1,j)]+=val;
}
if(ctl==2)
{
if(i==ex&&j==ey)
ans+=val,ans%=mod;
if(g[i][j+1])
f[nxt][S^Get_s(2,j-1)^Get_s(2,j)]+=val;
f[nxt][S^Get_s(2,j-1)]+=val;
}
continue;
}
if(ctl==ctr&&ctl==1)
{
if(i==ex&&j==ey)
ans+=val,ans%=mod;
f[nxt][S^Get_s(1,j-1)^Get_s(1,j)]+=val;
continue;
}
}
f[now].clear();
now^=1;
}
for(auto k:f[now])
{
int S=k.first,val=k.second;
f[now^1][(S<<2)&mxn]+=val;
}
f[now].clear();
now^=1;
}
return 0;
}
bool Solve()
{
//freopen("test.in","r",stdin);
n=Read(); m=Read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
char in;
scanf(" %c",&in);
if(in=='_')
g[i][j]=1,ex=i,ey=j;//记录一下终点
}
if(n<m)
{
swap(n,m);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
gn[i][j]=g[j][i];
g[j][i]=0;
if(gn[i][j])
ex=i,ey=j;
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
g[i][j]=gn[i][j];
}
Ctdp();
printf("%lld\n",ans);
return true;
}
signed main()
{
//T=Read();
while(T--)
if(!Solve())
printf("-1\n");
return 0;
}
/*
3 3
___
_*_
___
*/