POJ 1739 Tony's Tour 解题报告(插头DP)

来源:互联网 发布:大屏幕控制软件 供应商 编辑:程序博客网 时间:2024/04/30 13:12

    楼教主男人八题之一,插头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));}}

    我们队三个水货搞定了男人八题中的四题,JX开玩笑说是不是就算半个楼教主了呢?无论未来如何,现在努力就好,开心就好。

原创粉丝点击