插头DP--URAL1519Formula 1

去年的老朋友。挺怀念的,回来看看。

$n \leq 12,m \leq 12$,$n*m$的01矩形,问在0中走路的欧拉回路数。答案保证longlong范围。

先设计插头:左右括号和空插头;然后分3*3种情况转移。耐心。

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 //#include<time.h>
 5 //#include<complex>
 6 #include<algorithm>
 7 #include<stdlib.h>
 8 using namespace std;
 9 
10 int n,m; bool mp[14][14];
11 #define maxn 2333333
12 #define LL long long
13 int state[2][maxn],len[2]; LL ans[2][maxn]; int cur;
14 int Next[maxn],first[maxn];
15 
16 void insert(int x,LL v)
17 {
18     int y=cur^1,h=x%maxn;
19     for (int i=first[h];i;i=Next[i]) if (state[y][i]==x) {ans[y][i]+=v; return;}
20     state[y][++len[y]]=x; ans[y][len[y]]=v;
21     Next[len[y]]=first[h]; first[h]=len[y];
22 }
23 
24 int main()
25 {
26     scanf("%d%d",&n,&m);
27     for (int i=1;i<=n;i++)
28         for (int j=1;j<=m;j++)
29         {
30             char c; while ((c=getchar())!='.' && c!='*');
31             mp[i][j]=(c=='*');
32         }
33     //0 kong di 1 zhang ai
34     
35     int endx=0,endy;
36     for (int i=n;i && !endx;i--)
37         for (int j=m;j;j--)
38             if (!mp[i][j]) {endx=i; endy=j; break;}
39     
40     cur=1; insert(0,1); cur=0; LL Ans=0;
41     for (int i=1;i<=n;i++)
42         for (int j=1;j<=m;j++)
43         {
44             for (int k=1;k<=len[cur];k++) first[state[cur][k]%maxn]=0;
45             for (int k=1;k<=len[cur];k++)
46             {
47                 int now=state[cur][k],p=now&3,q=(now>>2)&3,nk;
48                 if (mp[i][j]) {if (p==0 && q==0) nk=now>>2,insert(nk,ans[cur][k]);}
49                 else if (p==0 && q==0) {if (j<m) {nk=(now>>2)|2|(1<<(m<<1)); insert(nk,ans[cur][k]);}}
50                 else if (p==0 && q)
51                 {
52                     nk=((now>>2)^q)|(q<<(m<<1)); insert(nk,ans[cur][k]);
53                     if (j<m) {nk=now>>2; insert(nk,ans[cur][k]);}
54                 }
55                 else if (p && q==0)
56                 {
57                     nk=(now>>2)|(p<<(m<<1)); insert(nk,ans[cur][k]);
58                     if (j<m) {nk=(now>>2)|p; insert(nk,ans[cur][k]);}
59                 }
60                 else if (p==1 && q==1)
61                 {
62                     int cnt=1; nk=(now>>2)^q;
63                     for (int l=2;;l++)
64                     {
65                         int hh=(now>>(l<<1))&3;
66                         if (hh==1) cnt++; if (hh==2) cnt--;
67                         if (cnt==0) {nk=(nk^(2<<((l-1)<<1)))^(1<<((l-1)<<1)); break;}
68                     }
69                     insert(nk,ans[cur][k]);
70                 }
71                 else if (p==2 && q==1)
72                 {
73                     nk=(now>>2)^q;
74                     insert(nk,ans[cur][k]);
75                 }
76                 else if (p==1 && q==2) {if (i==endx && j==endy && (now^p^(q<<2))==0) Ans+=ans[cur][k];}
77                 else if (p==2 && q==2)
78                 {
79                     int cnt=1,nk=(now>>2)^q;
80                     for (int l=m;;l--)
81                     {
82                         int hh=(now>>(l<<1))&3;
83                         if (hh==2) cnt++; if (hh==1) cnt--;
84                         if (cnt==0) {nk=(nk^(1<<((l-1)<<1)))^(2<<((l-1)<<1)); break;}
85                     }
86                     insert(nk,ans[cur][k]);
87                 }
88             }
89             len[cur]=0;
90             cur^=1;
91         }
92     printf("%lld\n",Ans);
93     return 0;
94 }
View Code

 

posted @ 2018-04-14 07:01  Blue233333  阅读(132)  评论(0编辑  收藏  举报