解题思路:

分类讨论即可。

代码(懒得删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=;
  16. int mp[][];
  17. char cmd[];
  18. uit code[];
  19. uit tod[];
  20. int clor[];
  21. bool col[];
  22. std::map<unt,unt>dp[],ooo;
  23. void minpress(uit *cd)
  24. {
  25. int cnt=;
  26. memset(clor,,sizeof(clor));
  27. for(int i=;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=;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>=;i--)
  46. {
  47. cd[i]=sit%10ull;
  48. sit/=10ull;
  49. }
  50. cl[]=sit;
  51. for(int i=;i<=m;i++)
  52. if(cd[i]!=cd[i-])
  53. cl[i]=-cl[i-];
  54. else
  55. cl[i]=cl[i-];
  56. return ;
  57. }
  58. bool banned(int l,int r,int pos,uit *cd)
  59. {
  60. for(int i=;i<l;i++)
  61. if(cd[i]==cd[pos-])
  62. return false;
  63. for(int i=r-;i<=m;i++)
  64. if(cd[i]==cd[pos-])
  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[];
  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-]^b;
  89. ll=col[jj-]^b;
  90. /* printf(uu?"b":"w");
  91. printf(lu?"b":"w");
  92. printf(ll?"b":"w");*/
  93. // puts("");
  94. uit maxs=;
  95. for(int i=;i<=m;i++)
  96. maxs=std::max(maxs,code[i]);
  97. for(int i=;i<=m;i++)
  98. tod[i]=code[i];
  99. if(ll)
  100. {
  101. if(lu)
  102. {
  103. if(uu)
  104. tod[jj-]=maxs+;
  105. else
  106. tod[jj-]=tod[jj];
  107. }else{
  108. if(uu)
  109. {
  110. if(ii==n&&jj==m)
  111. return ;
  112. if(banned(jj-,jj+,jj+,tod))
  113. return ;
  114. //printf("+1\n");
  115. tod[jj-]=maxs+;
  116. }else
  117. tod[jj-]=tod[jj];
  118. }
  119. }else{
  120. if(lu)
  121. {
  122. if(uu)
  123. {
  124. if(banned(jj-,jj+,jj+,tod))
  125. {
  126. if(ii!=n||(jj!=m&&jj!=m-))return ;
  127. for(int i=;i<jj-;i++)
  128. if(col[i]==col[jj])
  129. return ;
  130. for(int i=jj+;i<=m;i++)
  131. if(col[i]==col[jj])
  132. return ;
  133. }
  134. tod[jj-]=tod[jj-];
  135. }else{
  136. tod[jj]=tod[jj-]=tod[jj-];
  137. for(int i=;i<=m;i++)
  138. {
  139. if(code[i]==code[jj]||code[i]==code[jj-])
  140. tod[i]=tod[jj-];
  141. }
  142. }
  143. }else{
  144. if(uu)
  145. {
  146. if(banned(jj-,jj+,jj+,tod))
  147. {
  148. if(ii!=n||(jj!=m&&jj!=m-))return ;
  149. for(int i=;i<jj-;i++)
  150. if(col[i]==col[jj])
  151. return ;
  152. for(int i=jj+;i<=m;i++)
  153. if(col[i]==col[jj])
  154. return ;
  155. }
  156. tod[jj-]=tod[jj-];
  157. }else return ;
  158. }
  159. }
  160. unt tmp=compress(tod,hc);
  161. if(ii==n&&jj==m)
  162. {
  163. int cnt=;
  164. decompress(code,col,tmp);
  165. memset(clor,,sizeof(clor));
  166. for(int i=;i<=m;i++)
  167. if(!clor[code[i]])
  168. clor[code[i]]=++cnt;
  169. if(cnt<=)
  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[];
  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=;i<=m;i++)
  186. tod[i]=code[i];
  187. uu=col[]^b;
  188. if(uu)
  189. {
  190. if(banned(,,,tod))
  191. return ;
  192. code[]=;
  193. hc=b;
  194. }else
  195. code[]=code[];
  196. unt tmp=compress(code,hc);
  197. if(i==n&&m==)
  198. {
  199. int cnt=;
  200. decompress(code,col,tmp);
  201. memset(clor,,sizeof(clor));
  202. for(int ii=;ii<=m;ii++)
  203. if(!clor[code[ii]])
  204. clor[code[ii]]=++cnt;
  205. if(cnt<=)
  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[];
  215. for(int i=m;i;i--)
  216. code[i]=code[i-];
  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[].clear();
  235. dp[].clear();
  236. ans=;
  237. p=,q=;
  238. memset(mp,,sizeof(mp));
  239. memset(code,,sizeof(code));
  240. memset(clor,,sizeof(clor));
  241. scanf("%d%d",&n,&m);
  242. for(int i=;i<=n;i++)
  243. {
  244. scanf("%s",cmd+);
  245. for(int j=;j<=m;j++)
  246. {
  247. if(cmd[j]==white)
  248. mp[i][j]=-;
  249. else if(cmd[j]==black)
  250. mp[i][j]=;
  251. else
  252. mp[i][j]=;
  253. }
  254. }
  255. if(n==&&m==)
  256. {
  257. if(mp[][])
  258. puts("");
  259. else
  260. puts("");
  261. return ;
  262. }
  263. for(int i=;i<(<<m);i++)
  264. {
  265. int cnt=;
  266. code[]=code[]=;
  267. bool ban=false;
  268. for(int j=;j<=m;j++)
  269. {
  270. if(mp[][j]==&&((i&(<<(j-)))==))ban=true;
  271. if(mp[][j]==-&&(i&(<<(j-)))) ban=true;
  272. if(ban)break;
  273. }
  274. if(ban)
  275. continue;
  276. for(int j=;j<=m;j++)
  277. {
  278. if((bool)(i&(<<(j-)))^(bool)(i&(<<(j-))))
  279. cnt++;
  280. code[j]=cnt;
  281. }
  282. int co=i&;
  283. // printf("%d ",co);
  284. // puts("");
  285. unt s=compress(code,co);
  286. // printf("%d\n",s);
  287. update(p,s,);
  288. }
  289. for(int i=;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][]!=)
  299. Insert(i,s,v,);
  300. if(mp[i][]!=-)
  301. Insert(i,s,v,);
  302. }
  303. // puts("_________________________");
  304. for(int j=;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]!=)
  314. Insert(i,j,s,v,);
  315. if(mp[i][j]!=-)
  316. Insert(i,j,s,v,);
  317. }
  318. // puts("_________________________");
  319. }
  320. // puts("%d");
  321. Move();
  322. }
  323. printf("%llu\n",ans);
  324. return ;
  325. }BLACK_AND_WHITE

BZOJ3336: Uva10572 Black and White(插头Dp)的更多相关文章

  1. BZOJ 3336 Black and White (插头DP)

    题目大意: 给你一个n×m的网格,有一些格子已经被涂上了白色或者黑色,让你用黑色或白色填剩下的格子,且填好的网格必须保证: 1.对于任意2×2的子矩阵的4个格子,它们的颜色不能都相同 2.所有黑色的块 ...

  2. bzoj3336 Uva10572 Black and White

    题目描述: 数据范围:2<=n,m<=8 题解: 很明显需要状压.但是怎么压不知道,压什么不知道. 然后从条件下手. 条件1要求黑色在一起白色在一起,记录轮廓线很容易做到. 条件2要求不能 ...

  3. 插头dp练习

    最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...

  4. 插头dp

    插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...

  5. HDU 4113 Construct the Great Wall(插头dp)

    好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...

  6. HDU 4949 Light(插头dp、位运算)

    比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...

  7. 插头DP专题

    建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...

  8. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

  9. HDU 1693 Eat the Trees(插头DP)

    题目链接 USACO 第6章,第一题是一个插头DP,无奈啊.从头看起,看了好久的陈丹琦的论文,表示木看懂... 大体知道思路之后,还是无法实现代码.. 此题是插头DP最最简单的一个,在一个n*m的棋盘 ...

随机推荐

  1. Boom

    紧急事件!战场内被敌军埋放了n枚炸弹! 我军情报部门通过技术手段,掌握了这些炸弹的信息.这些炸弹很特殊,每枚炸弹的波及区域是一个矩形.第i枚炸弹的波及区域是以点(xi1,yi1)为左下角,点(xi2, ...

  2. Audio / Video Playback

    For Developers‎ > ‎Design Documents‎ > ‎ Audio / Video Playback Interested in helping out?  Ch ...

  3. Linux 图形文件压缩/解压缩实用程序,归档管理器。

    1.ArkArk是KDE桌面环境默认的归档管理器,支持插件设置,允许你创建一个压缩包,查看压缩文件的内容,解压压缩包的内容到你所选定的目录.它能处理多种格式,包括 tar.gzip.bzip2.zip ...

  4. 并查集 (Union Find ) P - The Suspects

    Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized ...

  5. Timestamp 转 date

    Timestamp startTime = new Timestamp(new Date().getTime());

  6. 搭建Lvs负载均衡群集

    一.Lvs详解 lvs内核模型 1.模型分析 用户访问的数据可以进入调度器 匹配调度器分配的虚拟IP|IP+端口(路由走向) 根据调度器的算法确定匹配的服务器 2.调度条件:基于IP.基于端口.基于内 ...

  7. BZOJ 1305 二分+网络流

    思路: 建图我根本没有想到啊--. (我是不会告诉你我借鉴了一下题解的思路) 把每个人拆成喜欢的和不喜欢的点 男 喜欢 向 男 不喜欢 连 边权为k的边 如果男喜欢女 那么 男喜欢向 女喜欢 连 1 ...

  8. request获取各种路径总结、页面跳转总结。

    页面跳转总结 JSP中response.sendRedirect()与request.getRequestDispatcher().forward(request,response)这两个对象都可以使 ...

  9. Flex之登录界面

    制作登录框界面 环境搭建:MyEclipse 6.5+Flex Builder 3 Plug-in <?xml version="1.0" encoding="ut ...

  10. dedecms关键词维护里面字数多的词优先字数少的词的解决办法

    织梦后台的关键词维护默认的情况是字数少的词优先于字数多的词,比如我们有两个这样的词:创业.创业方向,第二个词包含了第一个词,在文章中如果出现“创业方向”这个词,默认情况下只会给创业两个字添加关键词超链 ...