poj1739 Tony's Tour 插头dp求哈密顿回路

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 10
#define M (1<<18)+2
int n,m;
int a[N][N];
int bb[N];
struct hash{
    int id[M],val[M],st[M];
    int cnt;
    void clear(){
       for(int i=1;i<=cnt;i++)id[st[i]]=0;
       cnt=0;    
    }
    void push(int x,int y){
        if(!id[x]){
        id[x]=++cnt;
        val[cnt]=y;
        st[cnt]=x;}else{
            val[id[x]]+=y;
        }
    }
    int cha(int x){
        if(!id[x])return -1;
        return val[id[x]];
    }
}T[2];
int gai(int x,int y,int z){
    return ((x&(~(1<<(2*y-2))))&(~(1<<(2*y-1))))+z*(1<<y*2-2);
}
void out(int x){
       for(int k=1;k<=m+1;k++){
                    cout<<((x>>((k-1)*2))&3);
        }
        cout<<" ";
}
int main(){
//    freopen("1.in","r",stdin);
    //freopen("2.out","w",stdout);
    while(1){
    scanf("%d%d",&n,&m);
     if(n==0&&m==0)break;
     memset(a,0,sizeof(a));
     for(int i=1;i<=n;i++){
         for(int j=1;j<=m;j++){
            char b;
            scanf(" %c",&b);
            if(b=='#'){
                a[i][j]=1;
            }
        }
      }
       T[0].clear();
       T[1].clear();
       T[0].push(0,1);
       int h=-1;
       for(int i=1;i<=n;i++){
            //cout<<endl;
            for(int j=1;j<=m;j++){
                h++;
                int u=h&1;
                int w=u^1;
                int vv=0;
                T[w].clear();
                for(int z=1;z<=T[u].cnt;z++){
                    int now=T[u].st[z];
                    vv=T[u].cha(now);
                    if(j==1){
                        if(now>>m*2){
                            continue;
                        }else{
                            now=gai(now,m+1,0)<<2;
                        }
                    }
                    for(int k=1;k<=m+1;k++){
                        bb[k]=(now>>((k-1)*2))&3;
                    }
                    if(a[i][j]){
                        if(bb[j]||bb[j+1]){
                            continue;
                        }else{
                            T[w].push(now,vv);
                            continue;
                        }
                    }
                    int now2=gai(gai(now,j,0),j+1,0);    
                        if(bb[j]==0){
                            if(bb[j+1]==0){
                                T[w].push(now2+((1+2*4)<<(j*2-2)),vv);
                            }
                            if(bb[j+1]==1){
                                T[w].push(now2+(1<<(j*2-2)),vv);
                                T[w].push(now2+((1*4)<<(j*2-2)),vv);
                            }
                            if(bb[j+1]==2){
                                T[w].push(now2+((2)<<(j*2-2)),vv);
                                T[w].push(now2+((2*4)<<(j*2-2)),vv);
                            }
                        }
                        if(bb[j]==1){
                            if(bb[j+1]==0){
                                T[w].push(now2+((1)<<(j*2-2)),vv);
                                T[w].push(now2+((1*4)<<(j*2-2)),vv);
                            }
                            if(bb[j+1]==1){
                                int tot=0;
                                for(int k=j+2;k<=m;k++){
                                    if(bb[k]==2)tot--;
                                    if(bb[k]==1)tot++;
                                    if(tot==-1){
                                        T[w].push(gai(now2,k,1),vv);break;
                                    }
                                }
                            }
                            /*if(bb[j+1]==2){
                                T[w].push(now2,vv);
                            }*/
                        }
                        if(bb[j]==2){
                            if(bb[j+1]==0){
                                T[w].push(gai(now2,j,2),vv);
                                T[w].push(gai(now2,j+1,2),vv);
                            }
                            if(bb[j+1]==1){
                                T[w].push(now2,vv);
                            }
                            if(bb[j+1]==2){
                                int tot=0;
                                for(int k=j-1;k>=1;k--){
                                    if(bb[k]==2)tot--;
                                    if(bb[k]==1)tot++;
                                    if(tot==1){
                                        T[w].push(gai(now2,k,2),vv);
                                        break;
                                    }
                                }
                            }
                        }
                }
            }
       }
       int hh=T[(h&1)^1].cha(1+(2<<(2*(m-1))));
       if(hh==-1)hh=0;
       printf("%d\n",hh);
    }
}

 

 

转载于:https://www.cnblogs.com/wangyucheng/p/3664654.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值