洛谷P5056 【模板】插头dp ural 1519

https://www.luogu.com.cn/problem/P5056

学习了模板题https://www.cnblogs.com/y2823774827y/p/10140757.html

关键在于知道b1b2是你枚举的那个方块左边和上边的插头,b1是竖着的边的插头,b2是横着的边的插头。

然后1表示是一个条线左端点,2表示是1条线右端点,用4进制来存012的状态,再讨论状压的转移,8种情况怎么转移

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=15;
const int hs=299987;

int n,m,ex,ey,now,last,mt,cnt[2];
ll ans;
int hd[hs+3],nxt[2<<24],inc[maxl],mark[hs+3];
int a[maxl][maxl],que[2][2<<24];
ll val[2][2<<24];
char s[maxl];

inline void prework()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=m;j++)
		if(s[j]=='.')
		{
			a[i][j]=1;
			ex=i;ey=j;
		}
	}
	inc[0]=1;
	for(int i=1;i<maxl;i++)
		inc[i]=inc[i-1]<<2;
}

inline void insert(int bit,ll num)
{
	int u=bit%hs+1;
	if(mark[u]!=mt)
		hd[u]=0,mark[u]=mt;
	for(int i=hd[u];i;i=nxt[i])
	if(que[now][i]==bit)
	{
		val[now][i]+=num;
		return;
	}
	nxt[++cnt[now]]=hd[u];
	hd[u]=cnt[now];
	que[now][cnt[now]]=bit;
	val[now][cnt[now]]=num;
}

inline void mainwork()
{
	int bit,b1,b2,top;ll num;
	cnt[now]=1;val[now][1]=1;que[now][1]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=cnt[now];j++)
			que[now][j]<<=2;
		for(int j=1;j<=m;j++)
		{
			++mt;
			last=now;now^=1;
			cnt[now]=0;
			for(int k=1;k<=cnt[last];k++)
			{
				bit=que[last][k];num=val[last][k];
				b1=(bit>>((j-1)*2))%4;
				b2=(bit>>(j*2))%4;
				if(!a[i][j])
				{
					if(!b1 && !b2)
						insert(bit,num);
				}else if(!b1 && !b2)
				{
					if(a[i+1][j] && a[i][j+1])
						insert(bit^inc[j-1]^(inc[j]*2),num);	
				}else if(b1 && !b2)
				{
					if(a[i+1][j])
						insert(bit,num);
					if(a[i][j+1])
						insert(bit^(inc[j-1]*b1)^(inc[j]*b1),num);
				}else if(!b1 && b2)
				{
					if(a[i][j+1])
						insert(bit,num);
					if(a[i+1][j])
						insert(bit^(inc[j]*b2)^(inc[j-1]*b2),num);
				}
				else if(b1==1 && b2==1)
				{
					top=1;
					for(int l=j+1;l<=m;l++)
					{
						if((bit>>(l*2))%4==1)
							++top;
						if((bit>>(l*2))%4==2)
							--top;
						if(!top)
						{
							insert((bit^inc[j-1]^inc[j])-inc[l],num);
							break;
						}
					}
				}else if(b1==2 && b2==2)
				{
					top=1;
					for(int l=j-2;l>=0;--l)
					{
						if((bit>>(l*2))%4==1)
							--top;
						if((bit>>(l*2))%4==2)
							++top;
						if(!top)
						{
							insert((bit^(inc[j-1]*2)^(inc[j]*2))+inc[l],num);
							break;
						}
					}
				}else if(b1==2 && b2==1)
					insert(bit^(inc[j-1]*2)^inc[j],num);
				else if(i==ex && j==ey)
					ans+=num;
			}
		}
	}
}

inline void print()
{
	printf("%lld",ans);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/108114948