大概就是强制要求从左下角开始在右下角结束的哈密顿路径
在图的下方加一两行:
.##########.
…………………
即可。或者在dp最后返回第一和第m个插头联通的状态也可以。
代码如下:
#include <iostream>
#include <cstring>
#include <map>
#define LL long long
using namespace std;
map<int,int> IH;
int n,m,H[40000],s;
LL d[2][40000];
char ch[10][10];
void getHash(int k,int x,int y)//y 未匹配的右括号
{
if(y<0||y>m-k+1)return;
if(k==m+1)IH[x]=s,H[s++]=x;
getHash(k+1,x<<2,y);
getHash(k+1,x<<2|2,y-1);
getHash(k+1,x<<2|3,y+1);
}
LL DP()
{
d[1][0]=1;
for(int i=1,cur=1;i<=n;i++,cur^=1)
{
for(int j=0;j<m;j++,cur^=1)
{
memset(d[cur^1],0,sizeof(d[cur^1]));
for(int k=0;k<s;k++)
{
long long temp=d[cur][k];
if(!temp)continue;
int t=H[k],x=t>>(j<<1)&3,y=t>>((j+1)<<1)&3;
if(ch[i][j]=='.')
{
if(x+y==3||x+y==2)
{
d[cur^1][k]+=temp;
d[cur^1][IH[t^((x|y)<<(j<<1))^((x|y)<<((j+1)<<1))]]+=temp;
}
if(x==3&&y==2)
{
d[cur^1][IH[t^(x<<(j<<1))^(y<<((j+1)<<1))]]+=temp;
}
if(x==0&&y==0)
{
d[cur^1][IH[t^(14<<(j<<1))]]+=temp;
}
if(x==2&&y==2)
{
for(int ii=j+2,jj=0;ii<=m;ii++)
{
if((t>>(ii<<1)&3)==2)jj++;
if((t>>(ii<<1)&3)==3)jj--;
if(jj<0)
{
d[cur^1][IH[t^(2<<(j<<1))^(2<<((j+1)<<1))^(1<<(ii<<1))]]+=temp;
break;
}
}
}
if(x==3&&y==3)
{
for(int ii=j-1,jj=0;ii>=0;ii--)
{
if((t>>(ii<<1)&3)==3)jj++;
if((t>>(ii<<1)&3)==2)jj--;
if(jj<0)
{
d[cur^1][IH[t^(3<<(j<<1))^(3<<((j+1)<<1))^(1<<(ii<<1))]]+=temp;
break;
}
}
}
}
else
{
if((x|y)==0)
{
d[cur^1][k]+=temp;
}
}
}
}
memset(d[cur^1],0,sizeof(d[cur^1]));
for(int j=0;H[j]<(1<<(m<<1));j++)
{
d[cur^1][IH[H[j]<<2]]=d[cur][j];
}
if(i==n)
{
return d[cur][IH[2|(3<<((m-1)<<1))]];
}
}
}
int main()
{
while(cin>>n>>m)
{
s=0;
memset(H,0,sizeof(H));
IH.clear();
memset(d,0,sizeof(d));
if(n==0)return 0;
for(int i=1;i<=n;i++)cin>>ch[i];
getHash(0,0,0);
cout<<DP()<<endl;
}
return 0;
}