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

猜你喜欢

转载自www.cnblogs.com/blog-Dr-J/p/10205761.html