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
 ___
 _*_
 ___
 
*/


posted @ 2023-04-04 22:39  模拟退火  阅读(14)  评论(0编辑  收藏  举报