洛谷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
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>((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;
}

 

你可能感兴趣的:(插头DP)