BZOJ1814: Ural 1519 Formula 1(插头Dp)
Description
Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well-known, that the city will conduct one of the Formula 1 events. Surely, for such an important thing a new race circuit should be built as well as hotels, restaurants, international airport - everything for Formula 1 fans, who will flood the city soon. But when all the hotels and a half of the restaurants were built, it appeared, that at the site for the future circuit a lot of gophers lived in their holes. Since we like animals very much, ecologists will never allow to build the race circuit over the holes. So now the mayor is sitting sadly in his office and looking at the map of the circuit with all the holes plotted on it. Problem Who will be smart enough to draw a plan of the circuit and keep the city from inevitable disgrace? Of course, only true professionals - battle-hardened programmers from the first team of local technical university!.. But our heroes were not looking for easy life and set much more difficult problem: "Certainly, our mayor will be glad, if we find how many ways of building the circuit are there!" - they said. It should be said, that the circuit in Vologda is going to be rather simple. It will be a rectangle N*M cells in size with a single circuit segment built through each cell. Each segment should be parallel to one of rectangle's sides, so only right-angled bends may be on the circuit. At the picture below two samples are given for N = M = 4 (gray squares mean gopher holes, and the bold black line means the race circuit). There are no other ways to build the circuit here. 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数
Input
The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop) means a cell, where a segment of the race circuit should be built, and character "*" (asterisk) - a cell, where a gopher hole is located.
Output
You should output the desired number of ways. It is guaranteed, that it does not exceed 2^63-1.
Sample Input
4 4
**..
....
....
....
**..
....
....
....
Sample Output
2
解题思路:
发现一个格点一定有一进一出,就可以3进制表示括号序列轮廓线Dp就好了。
把该存的存入map/Hash表中,元素访问状态转移,要写好编码和解码。3进制改用4进制。
分类讨论一下,10种情况,画个图就好了。
方程只关心最后一个格点,可以滚动掉2维。
代码:(Hash挂链)
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 typedef long long lnt; 6 typedef unsigned int uit; 7 typedef long long unt; 8 struct int_2{ 9 uit x; 10 unt y; 11 int_2(){} 12 int_2(uit a,unt b){x=a;y=b;} 13 }; 14 class Fast_map{ 15 #define mod 2333 16 public: 17 bool find(uit x) 18 { 19 int y=x%mod; 20 for(int i=0;i<to[y].size();i++) 21 if(to[y][i].x==x) 22 return true; 23 return false; 24 } 25 void ins(uit x,unt v) 26 { 27 int f=x%mod; 28 to[f].push_back(int_2(x,v)); 29 return ; 30 } 31 void add(uit x,unt v) 32 { 33 int f=x%mod; 34 for(int i=0;i<to[f].size();i++) 35 if(to[f][i].x==x) 36 { 37 to[f][i].y+=v; 38 return ; 39 } 40 return ; 41 } 42 void clear(void) 43 { 44 for(int i=0;i<mod;i++) 45 to[i].clear(); 46 return ; 47 } 48 void start(void) 49 { 50 jjj=0; 51 iii=0; 52 while(iii<mod&&!to[iii].size()) 53 iii++; 54 return ; 55 } 56 bool going_on(void) 57 { 58 59 return iii<mod; 60 } 61 void go(void) 62 { 63 jjj++; 64 if(jjj<to[iii].size()) 65 return ; 66 jjj=0; 67 iii++; 68 while(iii<mod&&!to[iii].size()) 69 iii++; 70 return ; 71 } 72 int_2 ite(void) 73 { 74 return to[iii][jjj]; 75 } 76 void move(void) 77 { 78 for(int i=0;i<mod;i++) 79 for(int j=0;j<to[i].size();j++) 80 to[i][j].x<<=2; 81 return ; 82 } 83 private: 84 std::vector<int_2>to[mod]; 85 int iii,jjj; 86 #undef mod 87 }dp[2]; 88 int n,m; 89 int p,q; 90 int ei,ej; 91 unt ans; 92 char cmd[20]; 93 bool mp[15][15]; 94 void update(int i,uit j,unt val) 95 { 96 if(!dp[i].find(j)) 97 dp[i].ins(j,val); 98 else 99 dp[i].add(j,val); 100 return ; 101 } 102 uit change(uit x,int plc,uit val) 103 { 104 uit ans=x; 105 uit cut=0ul-1ul; 106 cut^=(1<<(plc<<1)); 107 cut^=(1<<(plc<<1|1)); 108 ans&=cut; 109 ans|=(val<<(plc<<1)); 110 return ans; 111 } 112 int main() 113 { 114 memset(mp,0,sizeof(mp)); 115 scanf("%d%d",&n,&m); 116 for(int i=1;i<=n;i++) 117 { 118 scanf("%s",cmd+1); 119 for(int j=1;j<=m;j++) 120 { 121 if(cmd[j]=='.') 122 { 123 mp[i][j]=true; 124 ei=i,ej=j; 125 } 126 } 127 } 128 p=0,q=1; 129 dp[0].ins(0,1); 130 for(int i=1;i<=n;i++) 131 { 132 for(int j=1;j<=m;j++) 133 { 134 std::swap(p,q); 135 dp[p].clear(); 136 for(dp[q].start();dp[q].going_on();dp[q].go()) 137 { 138 int_2 state=dp[q].ite(); 139 uit s=state.x; 140 unt v=state.y; 141 uit tl=(s>>((j-1)<<1))&3; 142 uit tu=(s>>(j<<1))&3; 143 if(!mp[i][j]) 144 { 145 if(tl|tu);else 146 update(p,s,v); 147 }else{ 148 uit ts; 149 if(tl==0) 150 { 151 if(tu==0) 152 { 153 if(mp[i][j+1]&&mp[i+1][j]);else continue; 154 ts=change(s,j-1,1); 155 ts=change(ts,j,2); 156 update(p,ts,v); 157 }else if(tu==1) 158 { 159 if(mp[i+1][j]) 160 { 161 ts=change(s,j-1,1); 162 ts=change(ts,j,0); 163 update(p,ts,v); 164 } 165 if(mp[i][j+1]) 166 { 167 ts=change(s,j-1,0); 168 ts=change(ts,j,1); 169 update(p,ts,v); 170 } 171 }else{ 172 if(mp[i+1][j]) 173 { 174 ts=change(s,j-1,2); 175 ts=change(ts,j,0); 176 update(p,ts,v); 177 } 178 if(mp[i][j+1]) 179 { 180 ts=change(s,j-1,0); 181 ts=change(ts,j,2); 182 update(p,ts,v); 183 } 184 } 185 }else if(tl==1) 186 { 187 if(tu==0) 188 { 189 if(mp[i+1][j]) 190 { 191 ts=change(s,j-1,1); 192 ts=change(ts,j,0); 193 update(p,ts,v); 194 } 195 if(mp[i][j+1]) 196 { 197 ts=change(s,j-1,0); 198 ts=change(ts,j,1); 199 update(p,ts,v); 200 } 201 }else if(tu==1) 202 { 203 int cnt=1; 204 for(int kt=j+1;kt<=m;kt++) 205 { 206 if(((s>>(kt<<1))&3)==1) 207 cnt++; 208 if(((s>>(kt<<1))&3)==2) 209 cnt--; 210 if(!cnt) 211 { 212 ts=change(s,kt,1); 213 break; 214 } 215 } 216 ts=change(ts,j-1,0); 217 ts=change(ts,j,0); 218 update(p,ts,v); 219 }else{ 220 if(i==ei&&j==ej) 221 ans+=v; 222 } 223 }else{ 224 if(tu==0) 225 { 226 if(mp[i+1][j]) 227 { 228 ts=change(s,j-1,2); 229 ts=change(ts,j,0); 230 update(p,ts,v); 231 } 232 if(mp[i][j+1]) 233 { 234 ts=change(s,j-1,0); 235 ts=change(ts,j,2); 236 update(p,ts,v); 237 } 238 }else if(tu==1) 239 { 240 ts=change(s,j-1,0); 241 ts=change(ts,j,0); 242 update(p,ts,v); 243 }else{ 244 int cnt=-1; 245 for(int kt=j-2;kt>=0;kt--) 246 { 247 if(((s>>(kt<<1))&3)==1) 248 cnt++; 249 if(((s>>(kt<<1))&3)==2) 250 cnt--; 251 if(!cnt) 252 { 253 ts=change(s,kt,2); 254 break; 255 } 256 } 257 ts=change(ts,j-1,0); 258 ts=change(ts,j,0); 259 update(p,ts,v); 260 } 261 } 262 } 263 } 264 } 265 dp[p].move(); 266 } 267 printf("%lld\n",ans); 268 return 0; 269 }
代码(map)
1 #include<map> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 typedef long long lnt; 6 typedef unsigned int uit; 7 typedef long long unt; 8 using std::make_pair; 9 int n,m; 10 int p,q; 11 int ei,ej; 12 unt ans; 13 char cmd[20]; 14 bool mp[15][15]; 15 std::map<uit,unt>dp[2],ooo; 16 void update(int i,uit j,unt val) 17 { 18 if(dp[i].find(j)==dp[i].end()) 19 dp[i][j]=val; 20 else 21 dp[i][j]+=val; 22 return ; 23 } 24 uit change(uit x,int plc,uit val) 25 { 26 uit ans=x; 27 uit cut=0ul-1ul; 28 cut^=(1<<(plc<<1)); 29 cut^=(1<<(plc<<1|1)); 30 ans&=cut; 31 ans|=(val<<(plc<<1)); 32 return ans; 33 } 34 int main() 35 { 36 memset(mp,0,sizeof(dp)); 37 scanf("%d%d",&n,&m); 38 for(int i=1;i<=n;i++) 39 { 40 scanf("%s",cmd+1); 41 for(int j=1;j<=m;j++) 42 { 43 if(cmd[j]=='.') 44 { 45 mp[i][j]=true; 46 ei=i,ej=j; 47 } 48 } 49 } 50 p=0,q=1; 51 dp[0][0]=1; 52 for(int i=1;i<=n;i++) 53 { 54 for(int j=1;j<=m;j++) 55 { 56 std::swap(p,q); 57 dp[p].clear(); 58 for(std::map<uit,unt>::iterator State=dp[q].begin();State!=dp[q].end();State++) 59 { 60 uit s=State->first; 61 unt v=State->second; 62 uit tl=(s>>((j-1)<<1))&3; 63 uit tu=(s>>(j<<1))&3; 64 if(!mp[i][j]) 65 { 66 if(tl|tu);else 67 update(p,s,v); 68 }else{ 69 uit ts; 70 if(tl==0) 71 { 72 if(tu==0) 73 { 74 if(mp[i][j+1]&&mp[i+1][j]);else continue; 75 ts=change(s,j-1,1); 76 ts=change(ts,j,2); 77 update(p,ts,v); 78 }else if(tu==1) 79 { 80 if(mp[i+1][j]) 81 { 82 ts=change(s,j-1,1); 83 ts=change(ts,j,0); 84 update(p,ts,v); 85 } 86 if(mp[i][j+1]) 87 { 88 ts=change(s,j-1,0); 89 ts=change(ts,j,1); 90 update(p,ts,v); 91 } 92 }else{ 93 if(mp[i+1][j]) 94 { 95 ts=change(s,j-1,2); 96 ts=change(ts,j,0); 97 update(p,ts,v); 98 } 99 if(mp[i][j+1]) 100 { 101 ts=change(s,j-1,0); 102 ts=change(ts,j,2); 103 update(p,ts,v); 104 } 105 } 106 }else if(tl==1) 107 { 108 if(tu==0) 109 { 110 if(mp[i+1][j]) 111 { 112 ts=change(s,j-1,1); 113 ts=change(ts,j,0); 114 update(p,ts,v); 115 } 116 if(mp[i][j+1]) 117 { 118 ts=change(s,j-1,0); 119 ts=change(ts,j,1); 120 update(p,ts,v); 121 } 122 }else if(tu==1) 123 { 124 int cnt=1; 125 for(int kt=j+1;kt<=m;kt++) 126 { 127 if(((s>>(kt<<1))&3)==1) 128 cnt++; 129 if(((s>>(kt<<1))&3)==2) 130 cnt--; 131 if(!cnt) 132 { 133 ts=change(s,kt,1); 134 break; 135 } 136 } 137 ts=change(ts,j-1,0); 138 ts=change(ts,j,0); 139 update(p,ts,v); 140 }else{ 141 if(i==ei&&j==ej) 142 ans+=v; 143 } 144 }else{ 145 if(tu==0) 146 { 147 if(mp[i+1][j]) 148 { 149 ts=change(s,j-1,2); 150 ts=change(ts,j,0); 151 update(p,ts,v); 152 } 153 if(mp[i][j+1]) 154 { 155 ts=change(s,j-1,0); 156 ts=change(ts,j,2); 157 update(p,ts,v); 158 } 159 }else if(tu==1) 160 { 161 ts=change(s,j-1,0); 162 ts=change(ts,j,0); 163 update(p,ts,v); 164 }else{ 165 int cnt=-1; 166 for(int kt=j-2;kt>=0;kt--) 167 { 168 if(((s>>(kt<<1))&3)==1) 169 cnt++; 170 if(((s>>(kt<<1))&3)==2) 171 cnt--; 172 if(!cnt) 173 { 174 ts=change(s,kt,2); 175 break; 176 } 177 } 178 ts=change(ts,j-1,0); 179 ts=change(ts,j,0); 180 update(p,ts,v); 181 } 182 } 183 } 184 } 185 } 186 ooo.clear(); 187 for(std::map<uit,unt>::iterator j=dp[p].begin();j!=dp[p].end();j++) 188 if(!((j->first)>>(m<<1))) 189 ooo[((j->first)<<2)]=j->second; 190 dp[p].clear(); 191 for(std::map<uit,unt>::iterator j=ooo.begin();j!=ooo.end();j++) 192 dp[p][j->first]=j->second; 193 } 194 printf("%lld\n",ans); 195 return 0; 196 }