BZOJ3336: Uva10572 Black and White(插头Dp)
解题思路:
分类讨论即可。
代码(懒得删Debug了):
1 #include<map> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 #define black '#' 7 #define white 'o' 8 #define BLACK_AND_WHITE int main(){/*freopen("a.in","r",stdin);*/scanf("%d",&T);while(T--)Black_and_White();return 0;} 9 typedef long long lnt; 10 typedef unsigned int uit; 11 typedef unsigned long long unt; 12 int T; 13 int n,m; 14 int p,q; 15 unt ans=0; 16 int mp[20][20]; 17 char cmd[100]; 18 uit code[100]; 19 uit tod[100]; 20 int clor[31]; 21 bool col[100]; 22 std::map<unt,unt>dp[2],ooo; 23 void minpress(uit *cd) 24 { 25 int cnt=0; 26 memset(clor,0,sizeof(clor)); 27 for(int i=0;i<=m;i++) 28 { 29 if(!clor[cd[i]]) 30 clor[cd[i]]=++cnt; 31 cd[i]=clor[cd[i]]; 32 } 33 return ; 34 } 35 unt compress(uit *cd,int hc) 36 { 37 unt ret=hc; 38 minpress(cd); 39 for(int i=0;i<=m;i++) 40 ret=ret*10ull+cd[i]; 41 return ret; 42 } 43 void decompress(uit *cd,bool *cl,unt sit) 44 { 45 for(int i=m;i>=0;i--) 46 { 47 cd[i]=sit%10ull; 48 sit/=10ull; 49 } 50 cl[0]=sit; 51 for(int i=1;i<=m;i++) 52 if(cd[i]!=cd[i-1]) 53 cl[i]=1-cl[i-1]; 54 else 55 cl[i]=cl[i-1]; 56 return ; 57 } 58 bool banned(int l,int r,int pos,uit *cd) 59 { 60 for(int i=0;i<l;i++) 61 if(cd[i]==cd[pos-1]) 62 return false; 63 for(int i=r-1;i<=m;i++) 64 if(cd[i]==cd[pos-1]) 65 return false; 66 return true; 67 } 68 void update(int cmd,unt tmp,unt v) 69 { 70 if(dp[cmd].find(tmp)==dp[cmd].end()) 71 dp[cmd][tmp]=v; 72 else 73 dp[cmd][tmp]+=v; 74 return ; 75 } 76 void Insert(int ii,int jj,unt s,unt v,bool b) 77 { 78 decompress(code,col,s); 79 int lu,uu,ll,hc=col[0]; 80 /* printf("%d ",hc); 81 for(int k=0;k<=m;k++) 82 printf("%d ",code[k]); 83 printf("%d",v); 84 /* puts("");/* 85 for(int i=0;i<=m;i++) 86 printf("%d ",col[i]);*/ 87 uu=col[jj]^b; 88 lu=col[jj-1]^b; 89 ll=col[jj-2]^b; 90 /* printf(uu?"b":"w"); 91 printf(lu?"b":"w"); 92 printf(ll?"b":"w");*/ 93 // puts(""); 94 uit maxs=0; 95 for(int i=0;i<=m;i++) 96 maxs=std::max(maxs,code[i]); 97 for(int i=0;i<=m;i++) 98 tod[i]=code[i]; 99 if(ll) 100 { 101 if(lu) 102 { 103 if(uu) 104 tod[jj-1]=maxs+1; 105 else 106 tod[jj-1]=tod[jj]; 107 }else{ 108 if(uu) 109 { 110 if(ii==n&&jj==m) 111 return ; 112 if(banned(jj-2,jj+2,jj+1,tod)) 113 return ; 114 //printf("+1\n"); 115 tod[jj-1]=maxs+1; 116 }else 117 tod[jj-1]=tod[jj]; 118 } 119 }else{ 120 if(lu) 121 { 122 if(uu) 123 { 124 if(banned(jj-2,jj+2,jj+1,tod)) 125 { 126 if(ii!=n||(jj!=m&&jj!=m-1))return ; 127 for(int i=0;i<jj-2;i++) 128 if(col[i]==col[jj]) 129 return ; 130 for(int i=jj+1;i<=m;i++) 131 if(col[i]==col[jj]) 132 return ; 133 } 134 tod[jj-1]=tod[jj-2]; 135 }else{ 136 tod[jj]=tod[jj-1]=tod[jj-2]; 137 for(int i=0;i<=m;i++) 138 { 139 if(code[i]==code[jj]||code[i]==code[jj-2]) 140 tod[i]=tod[jj-2]; 141 } 142 } 143 }else{ 144 if(uu) 145 { 146 if(banned(jj-2,jj+2,jj+1,tod)) 147 { 148 if(ii!=n||(jj!=m&&jj!=m-1))return ; 149 for(int i=0;i<jj-2;i++) 150 if(col[i]==col[jj]) 151 return ; 152 for(int i=jj+1;i<=m;i++) 153 if(col[i]==col[jj]) 154 return ; 155 } 156 tod[jj-1]=tod[jj-2]; 157 }else return ; 158 } 159 } 160 unt tmp=compress(tod,hc); 161 if(ii==n&&jj==m) 162 { 163 int cnt=0; 164 decompress(code,col,tmp); 165 memset(clor,0,sizeof(clor)); 166 for(int i=0;i<=m;i++) 167 if(!clor[code[i]]) 168 clor[code[i]]=++cnt; 169 if(cnt<=2) 170 ans+=v; 171 return ; 172 } 173 update(p,tmp,v); 174 return ; 175 } 176 void Insert(int i,unt s,unt v,bool b) 177 { 178 decompress(code,col,s); 179 int uu,hc=col[0]; 180 /* printf("%d ",hc); 181 for(int k=0;k<=m;k++) 182 printf("%d ",code[k]); 183 printf("%d ",v); 184 puts("");*/ 185 for(int i=0;i<=m;i++) 186 tod[i]=code[i]; 187 uu=col[1]^b; 188 if(uu) 189 { 190 if(banned(0,3,2,tod)) 191 return ; 192 code[0]=0; 193 hc=b; 194 }else 195 code[0]=code[1]; 196 unt tmp=compress(code,hc); 197 if(i==n&&m==1) 198 { 199 int cnt=0; 200 decompress(code,col,tmp); 201 memset(clor,0,sizeof(clor)); 202 for(int ii=0;ii<=m;ii++) 203 if(!clor[code[ii]]) 204 clor[code[ii]]=++cnt; 205 if(cnt<=2) 206 ans+=v; 207 } 208 update(p,tmp,v); 209 return ; 210 } 211 unt move(unt x) 212 { 213 decompress(code,col,x); 214 int hc=col[0]; 215 for(int i=m;i;i--) 216 code[i]=code[i-1]; 217 return compress(code,hc); 218 } 219 void Move(void) 220 { 221 ooo.clear(); 222 for(std::map<unt,unt>::iterator i=dp[p].begin();i!=dp[p].end();i++) 223 ooo[i->first]=i->second; 224 dp[p].clear(); 225 for(std::map<unt,unt>::iterator i=ooo.begin();i!=ooo.end();i++) 226 { 227 update(p,move(i->first),i->second); 228 // printf("%I64u %I64u\n",move(i->first),i->second); 229 } 230 return ; 231 } 232 void Black_and_White(void) 233 { 234 dp[0].clear(); 235 dp[1].clear(); 236 ans=0; 237 p=1,q=0; 238 memset(mp,0,sizeof(mp)); 239 memset(code,0,sizeof(code)); 240 memset(clor,0,sizeof(clor)); 241 scanf("%d%d",&n,&m); 242 for(int i=1;i<=n;i++) 243 { 244 scanf("%s",cmd+1); 245 for(int j=1;j<=m;j++) 246 { 247 if(cmd[j]==white) 248 mp[i][j]=-1; 249 else if(cmd[j]==black) 250 mp[i][j]=1; 251 else 252 mp[i][j]=0; 253 } 254 } 255 if(n==1&&m==1) 256 { 257 if(mp[1][1]) 258 puts("2"); 259 else 260 puts("1"); 261 return ; 262 } 263 for(int i=0;i<(1<<m);i++) 264 { 265 int cnt=1; 266 code[0]=code[1]=1; 267 bool ban=false; 268 for(int j=1;j<=m;j++) 269 { 270 if(mp[1][j]==1&&((i&(1<<(j-1)))==0))ban=true; 271 if(mp[1][j]==-1&&(i&(1<<(j-1)))) ban=true; 272 if(ban)break; 273 } 274 if(ban) 275 continue; 276 for(int j=2;j<=m;j++) 277 { 278 if((bool)(i&(1<<(j-1)))^(bool)(i&(1<<(j-2)))) 279 cnt++; 280 code[j]=cnt; 281 } 282 int co=i&1; 283 // printf("%d ",co); 284 // puts(""); 285 unt s=compress(code,co); 286 // printf("%d\n",s); 287 update(p,s,1); 288 } 289 for(int i=2;i<=n;i++) 290 { 291 // puts("\n~~~~~~~~~~~~~~~~~~~~~~"); 292 std::swap(p,q); 293 dp[p].clear(); 294 for(std::map<unt,unt>::iterator k=dp[q].begin();k!=dp[q].end();k++) 295 { 296 unt s=k->first; 297 unt v=k->second; 298 if(mp[i][1]!=1) 299 Insert(i,s,v,0); 300 if(mp[i][1]!=-1) 301 Insert(i,s,v,1); 302 } 303 // puts("_________________________"); 304 for(int j=2;j<=m;j++) 305 { 306 // puts("\n~~~~~~~~~~~~~~~~~~~~~~"); 307 std::swap(p,q); 308 dp[p].clear(); 309 for(std::map<unt,unt>::iterator k=dp[q].begin();k!=dp[q].end();k++) 310 { 311 unt s=k->first; 312 unt v=k->second; 313 if(mp[i][j]!=1) 314 Insert(i,j,s,v,0); 315 if(mp[i][j]!=-1) 316 Insert(i,j,s,v,1); 317 } 318 // puts("_________________________"); 319 } 320 // puts("%d"); 321 Move(); 322 } 323 printf("%llu\n",ans); 324 return ; 325 }BLACK_AND_WHITE