URAL - 1519 Formula 1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yzyyylx/article/details/83510382

题面

题意

给出一张网格图,用一条哈密顿回路覆盖它的所有格子,问有几种方案。

做法

这道题与HDU - 1693 Eat the Trees的区别在于此题只有一条回路,因此dp方法有所不同。
同样是插头dp,可以发现对于每一条合法的回路,沿轮廓线将其切成两部分后,轮廓线上面的部分是多个联通块,且每个联通块与轮廓线恰好有两个交点,可以用括号序列来维护这两个交点,然后逐格递推时分情况转移即可,但因为状态总数为 O ( m n 3 n + 1 ) O(m*n*3^{n+1}) ,所以在转移时只要记录方案数非零的状态转移即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define N 15
#define M 1600000
using namespace std;

ll m,n,dp[2][M],san[N],li,lj,ans;
char str[N];
bool mm[N][N],in[M],now,cur;
vector<ll>have[2];

inline ll get(ll u,ll v){return u/san[v-1]%3;}
inline ll chg(ll u,ll v,ll w){return u+(w-get(u,v))*san[v-1];}
inline void add(ll u,ll v)
{
	if(!dp[now][u]) have[now].push_back(u);
	dp[now][u]+=v;
}

int main()
{
	ll i,j,k,kk,t,l,p,q,jb;
	cin>>m>>n;
	san[0]=1;
	for(i=1;i<=n+1;i++) san[i]=san[i-1]*3;
	for(i=1;i<=m;i++)
	{
		scanf("%s",str+1);
		for(j=1;j<=n;j++)
		{
			if(str[j]=='*') mm[i][j]=1;
			else li=i,lj=j;
		}
		mm[i][0]=mm[i][n+1]=1;
	}
	for(i=0;i<=n+1;i++) mm[0][i]=mm[m+1][i]=1;
	now=1;
	add(0,1);
	for(i=1;i<=m;i++)
	{
		for(j=1;j<=n;j++)
		{
			swap(now,cur);
			have[now].clear();
			for(kk=0;kk<have[cur].size();kk++)
			{
				k=have[cur][kk];
				p=get(k,j),q=get(k,j+1);
				if(mm[i][j])
				{
					if(!p&&!q) add(k,dp[cur][k]);
				}
				else if(!p&&!q)
				{
					if(!mm[i+1][j] && !mm[i][j+1])
					{
						t=chg(k,j,1),t=chg(t,j+1,2);
						add(t,dp[cur][k]);
					}
				}
				else if(!p||!q)
				{
					t=chg(k,j,0),t=chg(t,j+1,0);
					if(!mm[i][j+1]) add(chg(t,j+1,p+q),dp[cur][k]);
					if(!mm[i+1][j]) add(chg(t,j,p+q),dp[cur][k]);
				}
				else if(p==2&&q==1)
				{
					t=chg(k,j,0),t=chg(t,j+1,0);
					add(t,dp[cur][k]);
				}
				else if(p==1&&q==1)
				{
					t=chg(k,j,0),t=chg(t,j+1,0),jb=0;
					for(l=j+2;;l++)
					{
						if(get(k,l)==1) jb++;
						else if(jb&&get(k,l)==2) jb--;
						else if(!jb&&get(k,l)==2) break;
					}
					t=chg(t,l,1);
					add(t,dp[cur][k]);
				}
				else if(p==2&&q==2)
				{
					t=chg(k,j,0),t=chg(t,j+1,0),jb=0;
					for(l=j-1;;l--)
					{
						if(get(k,l)==2) jb++;
						else if(jb&&get(k,l)==1) jb--;
						else if(!jb&&get(k,l)==1) break;
					}
					t=chg(t,l,2);
					add(t,dp[cur][k]);
				}
				else if(i==li&&j==lj) ans+=dp[cur][k];
				dp[cur][k]=0;
			}
		}
		swap(now,cur);
		have[now].clear();
		for(kk=0;kk<have[cur].size();kk++)
		{
			k=have[cur][kk];
			add(k*3,dp[cur][k]);
			dp[cur][k]=0;
		}
	}
	cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/yzyyylx/article/details/83510382
今日推荐