ZOJ 3466 The Hive II

  插头DP。。

  求用若干个回路走遍整张图的方案数。。然而格子是六边形的TAT

  想了好久...按照列来转移好写一点。。其实和正方形格子差不多?

  膜了标程才知道,如果回路数没有限制的话。。可以只记录有没有插头,而不用去记录插头属于哪个联通块。。

  (要是去记录插头属于哪个联通块就会爆long long了TAT

  代码依然很慢。。。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define ll long long
  6 using namespace std;
  7 const int maxzt=1023333,modd=6023,inf=1002333333;
  8 struct zs1{
  9     struct zs{
 10         int too,pre;
 11     }e[maxzt];int tot,last[modd];
 12     int zt[maxzt];
 13     ll f[maxzt];
 14     inline int get(int v){
 15         int i,x=v%modd;
 16         for(i=last[x];i&&e[i].too!=v;i=e[i].pre);
 17         if(i)return i;
 18         e[++tot].too=v,e[tot].pre=last[x],last[x]=tot;
 19         f[tot]=0,zt[tot]=v;
 20         return tot;
 21     }
 22 }hm[2];
 23 bool can[13][13];
 24 int mp[21];
 25 int i,j,k,n,m,ans;
 26 
 27 inline void upd(int &a,int b){if(b<a)a=b;}
 28 
 29 inline int encode(){
 30     int x=0;
 31     for(int i=0;i<n<<1;i++)x=x<<1|mp[i];return x;
 32 }
 33 inline void decode(int x){
 34     for(int i=n*2-1;i>=0;i--)mp[i]=x&1,x>>=1;
 35 }
 36 inline void clr(bool now){
 37     memset(hm[now].last,0,modd<<2);
 38     hm[now].tot=0;
 39 }
 40 inline void dp_blank(int x,int y,bool pre){
 41     int up,zx,zs,i,zt;ll f;bool now=pre^1;int posup,poszs,poszx,ys,yx;
 42     if(y&1)ys=x;else ys=x-1;yx=ys+1;
 43     clr(now);//printf("    %d,%d
",x,y);
 44     for(i=1;i<=hm[pre].tot;i++){
 45         zt=hm[pre].zt[i],f=hm[pre].f[i];
 46         if(x==1)zt>>=1;
 47         decode(zt);
 48 //        for(int j=0;j<n<<1;j++)printf(" %d",mp[j]);printf("   %lld
",f);
 49         if(y&1)posup=(x<<1)-2,poszs=(x<<1)-1,poszx=x<<1;
 50             else posup=max(0,(x<<1)-3),poszs=(x<<1)-2,poszx=(x<<1)-1;
 51         up=mp[posup],zs=mp[poszs],zx=mp[poszx];
 52 //        printf("   %d %d %d     %d %d %d
",up,zs,zx,posup,poszs,poszx);
 53         if(up+zs+zx==0){
 54             if(can[x+1][y]&&can[ys][y+1])
 55                 mp[poszs]=0,mp[poszx]=mp[posup]=1,
 56                 hm[now].f[ hm[now].get(encode()) ]+=f;
 57             if(can[x+1][y]&&can[yx][y+1])
 58                 mp[posup]=0,mp[poszx]=mp[poszs]=1,
 59                 hm[now].f[ hm[now].get(encode()) ]+=f;
 60             if(can[ys][y+1]&&can[yx][y+1])
 61                 mp[poszx]=0,mp[posup]=mp[poszs]=1,
 62                 hm[now].f[ hm[now].get(encode()) ]+=f;
 63         }
 64         if(up+zs+zx==1){
 65             if(can[x+1][y])
 66                 mp[poszs]=mp[posup]=0,mp[poszx]=1,
 67                 hm[now].f[ hm[now].get(encode()) ]+=f;
 68             if(can[ys][y+1])
 69                 mp[poszs]=mp[poszx]=0,mp[posup]=1,
 70                 hm[now].f[ hm[now].get(encode()) ]+=f;
 71             if(can[yx][y+1])//puts("yx"),
 72                 mp[posup]=mp[poszx]=0,mp[poszs]=1,
 73                 hm[now].f[ hm[now].get(encode()) ]+=f;
 74         }
 75         if(up+zs+zx==2)
 76             mp[poszx]=mp[poszs]=mp[posup]=0,
 77             hm[now].f[ hm[now].get(encode()) ]+=f;
 78     }
 79 }
 80 inline void dp_bar(int x,int y,bool pre){
 81     int i,up,zs,zx,zt;ll f;bool now=pre^1;int posup,poszs,poszx;
 82     
 83     clr(now);//printf("   # %d,%d
",x,y);
 84     for(i=1;i<=hm[pre].tot;i++){
 85         zt=hm[pre].zt[i],f=hm[pre].f[i];
 86         if(x==1)zt>>=1;
 87         decode(zt);
 88 //        for(int j=0;j<n<<1;j++)printf(" %d",mp[j]);printf("    %lld
",f);
 89         if(y&1)posup=(x<<1)-2,poszs=(x<<1)-1,poszx=x<<1;
 90             else posup=max(0,(x<<1)-3),poszs=(x<<1)-2,poszx=(x<<1)-1;
 91         up=mp[posup],zs=mp[poszs],zx=mp[poszx];
 92         if(up+zs+zx==0)
 93             hm[now].f[ hm[now].get(encode()) ]+=f;
 94     }
 95 }
 96 char s[23];
 97 int main(){
 98     while(scanf("%d",&n)!=EOF){
 99         scanf("%d",&m);
100         memset(can,0,sizeof(can));
101         for(i=1;i<=n;i++)for(j=1;j<=8;j++)can[i][j]=1;
102         for(i=1;i<=m;i++)scanf("%s",s),can[s[0]-'A'+1][s[1]-'A'+1]=0;
103         
104         bool now=1,pre=0;
105         clr(pre),hm[pre].f[ hm[pre].get(0) ]=1;
106         for(j=1;j<=8;j++)for(i=1;i<=n;swap(now,pre),i++)
107             if(can[i][j])dp_blank(i,j,pre);else dp_bar(i,j,pre);
108         ll ans=0;
109         for(i=1;i<=hm[pre].tot;i++)ans+=hm[pre].f[i];
110         printf("%lld
",ans);
111     }
112     return 0;
113 }
View Code

发现取模的数字会对效率有很大影响。。。。平时似乎不会啊= =

模数取10w出头就好了。。

原文地址:https://www.cnblogs.com/czllgzmzl/p/5491324.html