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;
}