插头DP模板

题目大意:给你一个n*m的网格图,求哈密顿回路数

插头DP板子题,搞了一天终于过了

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define N1 20
  6 #define M1 50010
  7 #define ll long long
  8 #define uint unsigned int
  9 #define il inline 
 10 #define jr 50000
 11 using namespace std;
 12 
 13 int n,m,now,pst,ex,ey;
 14 int mp[N1][N1];
 15 char str[N1];
 16 ll ans=0;
 17 struct Hash{
 18 int head[M1],nxt[M1],to[M1],cte;
 19 ll val[M1];
 20 void ae(int u,int v,int w){
 21     cte++;to[cte]=v,val[cte]=w;
 22     nxt[cte]=head[u],head[u]=cte;}
 23 void clr(){
 24     memset(head,0,sizeof(head));
 25     cte=0;}
 26 int find(int w){
 27     int x=w%jr;
 28     for(int j=head[x];j;j=nxt[j]){
 29         int v=to[j];
 30         if(v==w) return j;
 31     }return 0;}
 32 void update(int x,ll w){
 33     int i=find(x);
 34     if(!i) ae(x%jr,x,0),i=cte;
 35     val[i]+=w;}
 36 }h[2];
 37 void solve(int x,int y,int type)
 38 {
 39     int s,a,b,c,res;
 40     h[now].clr();
 41     for(int k=0;k<jr;k++)
 42     for(int j=h[pst].head[k];j;j=h[pst].nxt[j])
 43     {
 44         s=h[pst].to[j];
 45         a=(s>>(y*2))&3;
 46         b=(s>>((y+1)*2))&3;
 47         if(!mp[x][y]){
 48             if(!a&&!b) h[now].update(s,h[pst].val[j]);
 49         }else if(!a&&!b){
 50             if(mp[x][y+1]&&mp[x+1][y]) h[now].update(s^(1<<(y*2))^(2<<((y+1)*2)),h[pst].val[j]);
 51         }else if(a&&!b){
 52             if(mp[x][y+1]) h[now].update(s^(a<<(y*2))^(a<<((y+1)*2)),h[pst].val[j]);
 53             if(mp[x+1][y]) h[now].update(s,h[pst].val[j]);
 54         }else if(!a&&b){
 55             if(mp[x+1][y]) h[now].update(s^(b<<((y+1)*2))^(b<<(y*2)),h[pst].val[j]);
 56             if(mp[x][y+1]) h[now].update(s,h[pst].val[j]);
 57         }else if(a==2&&b==1){
 58             h[now].update(s^(2<<(y*2))^(1<<((y+1)*2)),h[pst].val[j]);
 59         }else if(a==2&&b==2){
 60             res=1;
 61             for(int i=y-1;i>=0;i--){
 62                 c=(s>>(i*2))&3;
 63                 if(c==2) res++;
 64                 if(c==1) res--;
 65                 if(!res){
 66                     h[now].update(s^(2<<(y*2))^(2<<((y+1)*2))^(3<<(i*2)),h[pst].val[j]);
 67                     break;}
 68             }
 69         }else if(a==1&&b==1){
 70             res=1;
 71             for(int i=y+2;i<=m;i++){
 72                 c=(s>>(i*2))&3;
 73                 if(c==1) res++;
 74                 if(c==2) res--;
 75                 if(!res){
 76                     h[now].update(s^(1<<(y*2))^(1<<((y+1)*2))^(3<<(i*2)),h[pst].val[j]);
 77                     break;}
 78             }
 79         }else if(a==1&&b==2&&x==ex&&y==ey)  
 80             ans+=h[pst].val[j];
 81     }
 82 }
 83 void right_move()
 84 {
 85     h[now].clr();
 86     for(int k=0;k<jr;k++)
 87     for(int j=h[pst].head[k];j;j=h[pst].nxt[j])
 88     {
 89         int s=h[pst].to[j];
 90         if(!h[pst].val[j]) continue;
 91         h[now].update(s<<2,h[pst].val[j]);
 92     }
 93 }
 94 
 95 int main()
 96 {
 97     //freopen("t2.in","r",stdin); 
 98     scanf("%d%d",&n,&m);
 99     for(int i=0;i<n;i++){
100         scanf("%s",str);
101         for(int j=0;j<m;j++)
102             if(str[j]=='.') mp[i][j]=1,ex=i,ey=j;
103     }
104     now=1,pst=0;
105     h[pst].update(0,1);
106     for(int i=0;i<n;i++){
107         for(int j=0;j<m;j++)
108         {
109             solve(i,j,mp[i][j]);
110             swap(now,pst);
111         }
112         right_move();
113         swap(now,pst);
114     }
115     printf("%lld
",ans);
116     return 0;
117 }
原文地址:https://www.cnblogs.com/guapisolo/p/10073165.html