楼教主男人八题之一,插头DP。可以直接用Ural1519的代码,将地图那块改下即可。如下图:
就是在原有的地图下方加入两行,求此图的哈密顿回路即可。
代码如下:
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; #define LL long long const int maxn=10007; int m,n; int now,pre; int maze[12][12]; struct Node { int H[maxn]; LL N[maxn]; int S[maxn]; int size; void init() { size=0; memset(H,-1,sizeof(H)); } void push(int SS,LL num) { int s=SS%maxn; while( ~H[s] && S[H[s]]!=SS ) s=(s+1)%maxn; if( ~H[s] ) { N[H[s]]+=num; } else { S[size]=SS; N[size]=num; H[s]=size++; } } LL get(int SS) { int s=SS%maxn; while( ~H[s] && S[H[s]]!=SS ) s=(s+1)%maxn; if( ~H[s] ) return N[H[s]]; return 0; } } dp[2]; int get(int S,int p,int l=2) { return (S>>(p*l))&((1<<l)-1); } void set(int& S,int p,int v,int l=2) { S^=get(S,p,l)<<(p*l); S^=(v&((1<<l)-1))<<(p*l); } void init() { memset(maze,0,sizeof(maze)); for(int i=0;i<n;i++) { char str[20]; scanf("%s",str); for(int j=0;j<m;j++) { if(str[j]=='#') maze[i][j]=0; else if(str[j]=='.') maze[i][j]=1; } } n+=2; for(int i=n-2;i<n;i++) for(int j=0;j<m;j++) maze[i][j]=1; for(int j=1;j<m-1;j++) maze[n-2][j]=0; } void solve() { now=1; pre=0; dp[now].init(); dp[now].push(0,1); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { swap(now,pre); dp[now].init(); for(int s=0;s<dp[pre].size;s++) { int S=dp[pre].S[s]; LL num=dp[pre].N[s]; int p=get(S,j); int q=get(S,j+1); if(maze[i][j]==0) { if(p==0 && q==0) dp[now].push(S,num); continue; } if(p==0 && q==0) { if(maze[i+1][j] && maze[i][j+1]) { set(S,j,1); set(S,j+1,2); dp[now].push(S,num); } } else if((p>0)^(q>0)) { if(maze[i+(p>0)][j+(q>0)]) dp[now].push(S,num); set(S,j,q); set(S,j+1,p); if(maze[i+(q>0)][j+(p>0)]) dp[now].push(S,num); } else if(p==1 && q==1) { int find=1; for(int k=j+2;k<=m;k++) { int v=get(S,k); if(v==1) find++; else if(v==2) find--; if(find==0) { set(S,j,0); set(S,j+1,0); set(S,k,1); dp[now].push(S,num); break; } } } else if(p==2 && q==2) { int find=1; for(int k=j-1;k>=0;k--) { int v=get(S,k); if(v==1) find--; else if(v==2) find++; if(find==0) { set(S,j,0); set(S,j+1,0); set(S,k,2); dp[now].push(S,num); break; } } } else if(p==2 && q==1) { set(S,j,0); set(S,j+1,0); dp[now].push(S,num); } else if(p==1 && q==2) { if(i==n-1 && j==m-1) { set(S,j,0); set(S,j+1,0); dp[now].push(S,num); } } } } for(int s=0;s<dp[now].size;s++) dp[now].S[s]<<=2; } } int main() { while( scanf("%d%d",&n,&m),n||m ) { init(); solve(); printf("%lld\n",dp[now].get(0)); } }