插头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 }
发现取模的数字会对效率有很大影响。。。。平时似乎不会啊= =
模数取10w出头就好了。。