好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错。

昨天看到的这题。

百度之后发现没有人发题解,hust也没,hdu也没discuss。。。在acm-icpc信息站发现难得的一篇题解。不过看到是插头二字之后,代码由于风格太不一样就没看了,自己想了好久,想通了。然后就等到今天才码。。。。

如果把点看成网格,那就可以实现,没有公共点公共边等限定条件,也显然是插头dp的最短单回路的模型。这是本题的一个难点(当时想到这样是因为,题目要求计算最短周长,显然这样建模便于求解)

另一个难点是如何保证那些OOXX在该在的位置,即题目所要求,O在单回路内部,X在单回路外部。我的做法是标记,加多一维01表示当前交点的左上角格子是否在内部。转移过程注意判断后续状态可否行即可。

这题要括号匹配,显然要用哈希表而不用数组。。。

虽然折腾时间挺久,但是1A的感觉还是不错的。

建议画图(其实所有插头dp都建议画图,便于分析,也不会占着电脑坑队友)

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <string>
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <queue>
  8. #include <vector>
  9. #include <set>
  10. #include <map>
  11. using namespace std;
  12.  
  13. #define inf 0x3f3f3f3f
  14. #define eps 1e-8
  15. #define ll long long
  16. #define maxm 51000
  17.  
  18. #define STATE 510000
  19. #define HASH 10007
  20. #define maxd 15
  21.  
  22. int n,m;
  23. char maze[maxd][maxd];
  24. int code[maxd];
  25. struct HASHMAP{
  26. int head[HASH],nxt[STATE],sz;
  27. int state[STATE],f[STATE];
  28. void clear(){sz=0;memset(head,-1,sizeof(head));}
  29. void push(int st,int ans){
  30. int h = st%HASH;
  31. for(int i=head[h];i!=-1;i=nxt[i]){
  32. if(st==state[i]){
  33. f[i] = min(f[i], ans);
  34. return ;
  35. }
  36. }
  37. state[sz]=st, f[sz]=ans, nxt[sz]=head[h];
  38. head[h]=sz++;
  39. }
  40. }hm[2][2];
  41. void decode(int st){
  42. for(int i=0;i<=m;++i) code[i] = st&3, st>>=2;
  43. }
  44. int encode(){
  45. int ret=0;
  46. for(int i=m;i>=0;--i) ret = ret<<2|code[i];
  47. return ret;
  48. }
  49. bool jud(int i,int j,int in){
  50. if(maze[i][j]=='o') return in;
  51. if(maze[i][j]=='x') return !in;
  52. return true;
  53. }
  54. int edx,edy;
  55. int ans;
  56. void dp(int i,int j,int cur,int in){
  57. int xo = (1<<(j*2));
  58. int ox = (2<<(j*2));
  59. int oo = xo|ox;
  60. int mv = (j==m?2:0);
  61. for(int k=0;k<hm[cur][in].sz;++k){
  62. decode(hm[cur][in].state[k]);
  63. int left = code[j-1];
  64. int up = code[j];
  65. if(left && up){
  66. if(left==2 && up==1){
  67. if(i>=edx+1 && j>=edy+1){
  68. int to = hm[cur][in].state[k] ^ (ox>>2) ^ (xo);
  69. if(to==0) ans = min(ans, hm[cur][in].f[k]+1);
  70. }
  71. continue;
  72. }
  73. if(left==1 && up==1){
  74. for(int jj=j-1,c=0;jj>=0;--jj){
  75. if(code[jj]==1)++c;
  76. if(code[jj]==2)--c;
  77. if(c==0){code[jj]^=3;break;}
  78. }
  79. code[j-1]=code[j]=0;
  80. }
  81. if(left==2 && up==2){
  82. for(int jj=j,c=0;jj<=m;++jj){
  83. if(code[jj]==2)++c;
  84. if(code[jj]==1)--c;
  85. if(c==0){code[jj]^=3;break;}
  86. }
  87. code[j-1]=code[j]=0;
  88. }
  89. if(left==1 && up==2){
  90. code[j-1]=code[j]=0;
  91. }
  92. if(jud(i-1,j,in^1))
  93. hm[cur^1][in^1].push(encode()<<mv, hm[cur][in].f[k]+1);
  94. }else if(left || up){
  95. int in2 = in;
  96. if(up) in2^=1;
  97. int tmp = left | up;
  98. code[j-1]=tmp, code[j]=0;
  99. if(i+1<=n)
  100. if(jud(i-1,j,in2) && jud(i,j-1,!in2) && jud(i,j,in2))
  101. hm[cur^1][in2].push(encode()<<mv, hm[cur][in].f[k]+1);
  102. code[j-1]=0, code[j]=tmp;
  103. if(j+1<=m)
  104. if(jud(i-1,j,in2) && jud(i,j-1,!in2) && jud(i,j,!in2))
  105. hm[cur^1][in2].push(encode()<<mv, hm[cur][in].f[k]+1);
  106. }else {
  107. if(jud(i-1,j,in) && jud(i,j-1,in) && jud(i,j,in))
  108. hm[cur^1][in].push(hm[cur][in].state[k]<<mv, hm[cur][in].f[k]);
  109. code[j-1]=2, code[j]=1;
  110. if(i+1<=n && j+1<=m)
  111. if(jud(i-1,j,in) && jud(i,j-1,in) && jud(i,j,!in))
  112. hm[cur^1][in].push(encode()<<mv, hm[cur][in].f[k]+1);
  113. }
  114. }
  115. }
  116. int solve(){
  117. int cur=0;
  118. hm[0][0].clear();
  119. hm[0][1].clear();
  120. hm[0][0].push(0,0);
  121. for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(maze[i][j]=='o') edx=i,edy=j;
  122. ans=inf;
  123. for(int i=1;i<=n;++i){
  124. for(int j=1;j<=m;++j){
  125. hm[cur^1][0].clear();
  126. hm[cur^1][1].clear();
  127. dp(i,j,cur,0);
  128. dp(i,j,cur,1);
  129. cur^=1;
  130. }
  131. }
  132. if(ans==inf) return -1;
  133. return ans;
  134. }
  135. int main(){
  136. int t,ca=0;
  137. scanf("%d",&t);
  138. while(t--){
  139. scanf("%d%d",&n,&m);
  140. memset(maze,0,sizeof(maze));
  141. for(int i=1;i<=n;++i) scanf("%s",maze[i]+1);
  142. ++n,++m;
  143. for(int i=0;i<=n;++i) maze[i][0]=maze[i][m]='.';
  144. for(int j=0;j<=m;++j) maze[0][j]=maze[n][j]='.';
  145. printf("Case #%d: %d\n",++ca, solve());
  146. }
  147. return 0;
  148. }

HDU 4113 Construct the Great Wall(插头dp)的更多相关文章

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

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

  2. HDU 1693 Eat the Trees(插头DP,入门题)

    Problem Description Most of us know that in the game called DotA(Defense of the Ancient), Pudge is a ...

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

    题意:给一个n*m的矩阵,为1时代表空格子,为0时代表障碍格子,问如果不经过障碍格子,可以画一至多个圆的话,有多少种方案?(n<12,m<12) 思路: 这题不需要用到最小表示法以及括号表 ...

  4. HDU 1693 二进制表示的简单插头dp

    题目大意: 找到多条回路覆盖所有非障碍格子,问这样回路的种数 这里的插头与URAL1519 不一样的是 只要管它是否存在即可,只需要1个二进制位表示状态 #include <cstdio> ...

  5. HDU 1565 方格取数(1) ——插头DP

    [题目分析] 其实直接状压就可以了. 但是有点闲,又写了一个可读性极差,智商低下,很(gou)好(pi)的代码 [代码] #include <cstdio> #include <cs ...

  6. hdu 1693 : Eat the Trees 【插头dp 入门】

    题目链接 题意: 给出一个n*m大小的01矩阵,在其中画线连成封闭图形,其中对每一个值为1的方格,线要恰好穿入穿出共两次,对每一个值为0的方格,所画线不能经过. 参考资料: <基于连通性状态压缩 ...

  7. HDU 4064 Carcassonne(插头DP)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4064 Problem Description Carcassonne is a tile-based ...

  8. hdu 1693 Eat the Trees——插头DP

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1693 第一道插头 DP ! 直接用二进制数表示状态即可. #include<cstdio> # ...

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

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

随机推荐

  1. tensorflow学习笔记三:实例数据下载与读取

    一.mnist数据 深度学习的入门实例,一般就是mnist手写数字分类识别,因此我们应该先下载这个数据集. tensorflow提供一个input_data.py文件,专门用于下载mnist数据,我们 ...

  2. .NET Web API 新手遇到的那些“坑”

    以前一直做web项目,用的mvc.最近公司需要上线APP,准备用webAPI做接口,用习惯了MVC,API还是有好多细节的地方感觉很“坑”... 第一个坑,webAPI的默认路由规则不一样,通过命名来 ...

  3. MySQL大小写补坑记

    背景:由于项目开始时数据库设计经验不足,数据库名和部分数据表名都含有大写字母.但问题是,Linux上数据库名和表名是区分大小写的,而Windows上是不区分大小写的.结果就是在看本地的数据库的时候,对 ...

  4. RCW 生存期控制

    RCW是.net 对com的包装,比如office就是通过RCW来被.net调用的.可以百度:office pia 了解更多信息. RCW 是一个.net类. 1.关闭线程对rcw的自动清理 Syst ...

  5. canvas实践1

    今天同学遇到问题,我于是就利用了canvas帮他写了个效果,效果如图 我本来在学习不是很想做,但是昨天感觉自己学的有点累就去帮忙做了,我的思路是每次画一个矩形,然后通过rotate旋转让它自身旋转45 ...

  6. Django 1.9 Post 时候出现 CSRF token missing or incorrect 错误

    get 的时候没有问题,只有在post的时候出现出现这个错误 在方法中加入 @csrf_exempt

  7. Spring MVC 处理静态资源不能访问问题

    在web.xml文件中加入如下代码: <servlet-mapping> <servlet-name>default</servlet-name> <url- ...

  8. 线段树 HDU 3397

    5种操作 具体看代码 #include<iostream> #include<stdio.h> #include<string.h> #include<alg ...

  9. redis配置详解

    ##redis配置详解 # Redis configuration file example. # # Note that in order to read the configuration fil ...

  10. jQuery倒计时插件

    倒计时jQuery插件 引言 最近又换工作了,还不错,我换工作的次数其实有点频繁,2014年7月份毕业,到现在工作已经换了3份了,工资跟刚毕业时候相比也涨了点儿,最近一次换工作我离开了深圳,来到了北京 ...