【插头dp】P5056 【模板】插头dp

有以下几种情况

情况就是这些

然而这道题目按照正常开点的话,空间会炸,所以使用了unordered_map来记录

还有一个细节就是有关三进制的取位数,修改操作

代码

#include<bits/stdc++.h>
#include<tr1/unordered_map>
using std::tr1::unordered_map;
unordered_map <int,long long>ump[14][14];
using namespace std;
typedef unordered_map <int,long long>::iterator ITR;
int ma[15][15],n,m,ex,ey,a[14],p[14],cnt;
int poww[15];
stack <int> st;
void part(int s)
{
	while(s)
	{
		a[++cnt]=s%3;
		s/=3;
	}
}
int pack()
{
	int ans=0;
	for(int j=1;j<=1+m;j++)
		ans+=a[j]*poww[j-1];
	return ans;
}
int uno(int x)
{
	return !(!x);
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%d%d",&n,&m);
	poww[0]=1;
	for(int i=1;i<=13;i++) poww[i]=poww[i-1]*3;
	for(int i=1;i<=n;i++)
	{
		char s[100];
		scanf("%s",s+1);
		for(int j=1;j<=m;j++)
			if(s[j]=='.')
			{
				ma[i][j]=1;
				ex=i;
				ey=j;
			}
	}
	ump[1][1][0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			for(ITR itr=ump[i][j].begin();itr!=ump[i][j].end();itr++)
			{
				int s=(*itr).first;
				//printf("ump[%d][%d][%d]=%lld\n",i,j,s,ump[i][j][s]);
				cnt=0; memset(a,0,sizeof(a));
				part(s);
				int left=a[j];
				int up=a[j+1];
				if(!ma[i][j])
				{
					if(!left && !up)
						ump[i][j+1][s]+=ump[i][j][s];
					continue;
				}
				int cnt=uno(left)+uno(up);
				if(!cnt)
				{
					if(!ma[i][j+1] || !ma[i+1][j])
						 continue;
					a[j+1]=2; a[j]=1;
					int k=pack();
					ump[i][j+1][k]+=ump[i][j][s];
					a[j+1]=up; a[j]=left;
					continue;
				}
				if(cnt==1)
				{
					if(ma[i][j+1])
					{
						a[j]=0; a[j+1]=max(up,left);
						int k=pack();
						ump[i][j+1][k]+=ump[i][j][s];
						a[j+1]=up; a[j]=left;
					}
					if(ma[i+1][j])
					{
						a[j]=max(up,left); a[j+1]=0;
						int k=pack();
						ump[i][j+1][k]+=ump[i][j][s];
						a[j+1]=up; a[j]=left;
					}
					continue;
				}
				for(int t=1;t<=m+1;t++)
				{
					if(a[t]==1) st.push(t);
					if(a[t]==2)
					{
						p[st.top()]=t;
						p[t]=st.top();
						st.pop();							
					}
				}
				if(left==up)
				{
					int ps=left==1?min(p[j],p[j+1]):max(p[j],p[j+1]);
					a[j]=0; a[j+1]=0; a[ps]=3-a[ps];
					int k=pack();
					ump[i][j+1][k]+=ump[i][j][s];
					a[j]=left; a[j+1]=up; a[ps]=3-a[ps];
				}
				else
				{
					if(p[j]!=j+1)
					{
						a[j]=0; a[j+1]=0;
						int k=pack();
						ump[i][j+1][k]+=ump[i][j][s];
						a[j]=left; a[j+1]=up;
					}
					else if(i==ex && j==ey)
					{
						a[j]=0; a[j+1]=0;
						int k=pack();
						ump[i][j+1][k]+=ump[i][j][s];
						a[j]=left; a[j+1]=up;
					}
				}
			}
		}
		for(ITR itr=ump[i][m+1].begin();itr!=ump[i][m+1].end();itr++)
		{
			int s=(*itr).first;
			//printf("ump[%d][%d][%d]=%lld\n",i,m+1,s,ump[i][m+1][s]);
			if(ump[i][m+1][s]) 
				ump[i+1][1][s*3]+=ump[i][m+1][s];
		}
	}
	printf("%lld",ump[n+1][1][0]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/andyc_03/article/details/107736494