hdu6875 Yajilin 2020杭电多校第9场

http://acm.hdu.edu.cn/showproblem.php?pid=6875

调了一个晚上,其实就是在求哈密尔顿路径的板题https://blog.csdn.net/liufengwei1/article/details/108114948的基础上加上一维状态表示那个插头是黑色方块,只有左插头和上插头都不是黑色,才能新增一个黑色方块。

然后有几个地方注意一下,左插头是1,右插头是2时,一定不能加进队列,因为要保证剩下的方格是一个完整的哈密尔顿路径,所以特判当i=n,j=n-1时,如果右边那个插头也是0,那么a[n][n]就可以加入答案里算

然后就是每次从上一行转到当前行的时候,注意处理一下最右边是3也就是是黑色方块的情况,把这个3减掉再乘以4.

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

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

int n,now,mt,ans,cnt[2];
int mark[hs+3],mi[maxl],hd[hs+3],nxt[hs+3];
int a[maxl][maxl],dp[2][hs+3],q[2][hs+3];

inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
}

inline void insert(int bit,int num)
{
	if(bit>mi[n+2])
	{
		return;
	}
	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(q[now][i]==bit)
	{
		dp[now][i]=max(dp[now][i],num);
		return;
	}
	nxt[++cnt[now]]=hd[u];
	hd[u]=cnt[now];
	q[now][cnt[now]]=bit;
	dp[now][cnt[now]]=num;
}

inline void mainwork()
{
	int b1,b2,bit,num,top,d;ans=0; 
	now=0;cnt[now]=1;q[now][1]=0;dp[now][1]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=cnt[now];j++)
		{
			d=(q[now][j]>>(n*2));
			if(d>0 && d!=3)
			{
				puts("wa");
			}
			q[now][j]-=d*mi[n];
			q[now][j]<<=2;
		}
		for(int j=1;j<=n;j++)
		{
			mt++;now^=1;cnt[now]=0;
			for(int k=1;k<=cnt[now^1];k++)
			{
				bit=q[now^1][k];num=dp[now^1][k];
				b1=(bit>>(2*(j-1)))%4;
				b2=(bit>>(2*j))%4;
				if((b1==0 || b1==3) && (b2==0 || b2==3))
				{
					if(b1==0 && b2==0)
					{
						insert(bit+mi[j-1]*3+mi[j]*3,num+a[i][j]);
						if(i==n && j==n)
							ans=max(ans,num+a[i][j]);
					}
					if(i<n && j<n)
						insert(bit+(1-b1)*mi[j-1]+(2-b2)*mi[j],num);
				}
				else if((b1==0 || b1==3) && b2>0)
				{
					if(i<n)
						insert(bit-b1*mi[j-1]-b2*mi[j]+b2*mi[j-1],num);
					if(j<n)
						insert(bit-b1*mi[j-1],num);
				}
				else if(b1>0 && (b2==0 || b2==3))
				{
					if(i<n)
						insert(bit-b2*mi[j],num);
					if(j<n)
						insert(bit-b2*mi[j]-b1*mi[j-1]+b1*mi[j],num);
				}
				else if(b1==2 && b2==1)
					insert(bit-b1*mi[j-1]-b2*mi[j],num);
				else if(b1==1 && b2==1)
				{
					top=1;
					for(int l=j+1;l<=n;l++)
					{
						d=(bit>>(l*2))%4;
						if(d==1) top++;
						if(d==2) top--;
						if(top==0)
						{
							insert(bit-mi[j-1]-mi[j]-mi[l],num);
							break;
						}
					}
				}
				else if(b1==2 && b2==2)
				{
					top=1;
					for(int l=j-2;l>=0;l--)
					{
						d=(bit>>(l*2))%4;
						if(d==1) top--;
						if(d==2) top++;
						if(!top)
						{
							insert(bit-2*mi[j-1]-2*mi[j]+mi[l],num);
							break;
						}
					}
				}
				else if(b1==1 && b2==2)
				{
					if(i==n && j==n)
						ans=max(num,ans);
					if(i==n && j==n-1 && (bit>>(2*n))==0)
						ans=max(ans,num+a[n][n]); 
				}
			}
		}
	}
}

inline void print()
{
	printf("%d\n",ans);
}

int main()
{
	mi[0]=1;
	for(int i=1;i<=12;i++)
		mi[i]=mi[i-1]<<2;
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

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