[NOIP2013]华容道

【题目描述】

  这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街。考后想想也是,数据这么小一定有他的道理。

  首先由于是最小步数,所以BFS没跑了。那么我们大可把这道题分为两部分,首先先把白格子移到目标棋子附近,然后再把目标棋子移过去。第一步是很容易的,随便BFS一下就好了,关键是第二步。由于q不小,我们不可能每次询问都直接爆搜,但由于棋盘并不会发生本质改变,我们可以对一些东西进行预处理。

  那每次询问时不变的是什么呢,我们求第二步时需要的又是什么呢?

  首先我们可以明确的是一个棋子得以移动一定是它移动的目标上是空的,而我们只有一个空格子,所以一旦我们确定了空格子的位置整个棋盘的状态就明了了,所以我们要处理的是当白格子在哪个位置时我想把当前棋子移到上下左右某一位置所要花费的最少步数,那么我们真的需要开5维去表示这一状态吗?不必,四维就够了,对于白格子从之前道这个点附近其实本质和第一步无异,而在我们执行第二步时白格子在每次转移完一定是在目标棋子的上下左右位置,所以我们只需要处理出来目标棋子在当前格子时白格子在他上下左右时他向上下左右移动所耗费的步数即可。

  然后,对于每一次询问,我们可以把每个点拆成四个,即白格子在这个点上下左右时的最小步数,慢慢搞即可。

  对了,提醒一下,对于某个格子进行处理的时候一定不能通过该点进行更新。

  

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<map>
  7. #include<queue>
  8. #include<string>
  9. #include<cmath>
  10. using namespace std;
  11. int n,m,q,a[][],zy[][],dis[][];
  12. struct no{int x,y,k;};
  13. bool check(int x,int y,int z){
  14. if(x+zy[z][]!=&&x+zy[z][]!=n+&&y+zy[z][]!=&&y+zy[z][]!=m+&&a[x+zy[z][]][y+zy[z][]]) return ;
  15. return ;
  16. }
  17. bool fw[][],f2[][];
  18. int f[][][][];
  19. void bfs1(int ax,int by){
  20. memset(dis,0x3f,sizeof(dis));
  21. memset(fw,,sizeof(fw));
  22. queue<no> q1;
  23. no aa;
  24. aa.x=ax,aa.y=by;
  25. dis[ax][by]=;
  26. q1.push(aa);
  27. fw[ax][by]=;
  28. while(!q1.empty())
  29. {
  30. no t=q1.front();
  31. q1.pop();
  32. int x=t.x,y=t.y;
  33. for(int i=;i<=;i++)
  34. {
  35. int xx=x+zy[i][],yy=y+zy[i][];
  36. if(xx==||xx==n+||yy==||yy==m+) continue;
  37. if(!a[xx][yy]) continue;
  38. if(f2[xx][yy]) continue;
  39. if(dis[xx][yy]>dis[x][y]+)
  40. {
  41. dis[xx][yy]=dis[x][y]+;
  42. if(!fw[xx][yy])
  43. {
  44. fw[xx][yy]=;
  45. no bb;
  46. bb.x=xx,bb.y=yy;
  47. q1.push(bb);
  48. }
  49. }
  50. }
  51. }
  52. }
  53. bool rd[][][];
  54. int dis2[][][];
  55. void spfa(int ax,int by){
  56. memset(rd,,sizeof(rd));
  57. no aa;
  58. queue<no> q1;
  59. aa.x=ax,aa.y=by;
  60. if(check(ax,by,))
  61. {
  62. aa.k=;
  63. q1.push(aa);
  64. rd[ax][by][]=;
  65. }
  66. if(check(ax,by,))
  67. {
  68. aa.k=;
  69. q1.push(aa);
  70. rd[ax][by][]=;
  71. }
  72. if(check(ax,by,))
  73. {
  74. aa.k=;
  75. q1.push(aa);
  76. rd[ax][by][]=;
  77. }
  78. if(check(ax,by,))
  79. {
  80. aa.k=;
  81. q1.push(aa);
  82. rd[ax][by][]=;
  83. }
  84. while(!q1.empty())
  85. {
  86. no bb=q1.front();q1.pop();
  87. int x=bb.x,y=bb.y,k=bb.k;
  88. rd[x][y][k]=;
  89. if(check(x,y,)&&dis2[x-][y][]>dis2[x][y][k]+f[x][y][][k]&&f[x][y][][k]!=-)
  90. {
  91. dis2[x-][y][]=dis2[x][y][k]+f[x][y][][k];
  92. if(!rd[x-][y][])
  93. {
  94. rd[x-][y][]=;
  95. no cc;
  96. cc.x=x-,cc.y=y,cc.k=;
  97. q1.push(cc);
  98. }
  99. }
  100. if(check(x,y,)&&dis2[x+][y][]>dis2[x][y][k]+f[x][y][][k]&&f[x][y][][k]!=-)
  101. {
  102. dis2[x+][y][]=dis2[x][y][k]+f[x][y][][k];
  103. if(!rd[x+][y][])
  104. {
  105. rd[x+][y][]=;
  106. no cc;
  107. cc.x=x+,cc.y=y,cc.k=;
  108. q1.push(cc);
  109. }
  110. }
  111. if(check(x,y,)&&dis2[x][y-][]>dis2[x][y][k]+f[x][y][][k]&&f[x][y][][k]!=-)
  112. {
  113. dis2[x][y-][]=dis2[x][y][k]+f[x][y][][k];
  114. if(!rd[x][y-][])
  115. {
  116. rd[x][y-][]=;
  117. no cc;
  118. cc.x=x,cc.y=y-,cc.k=;
  119. q1.push(cc);
  120. }
  121. }
  122. if(check(x,y,)&&dis2[x][y+][]>dis2[x][y][k]+f[x][y][][k]&&f[x][y][][k]!=-)
  123. {
  124. dis2[x][y+][]=dis2[x][y][k]+f[x][y][][k];
  125. if(!rd[x][y+][])
  126. {
  127. rd[x][y+][]=;
  128. no cc;
  129. cc.x=x,cc.y=y+,cc.k=;
  130. q1.push(cc);
  131. }
  132. }
  133. }
  134. }
  135. int main(){
  136. memset(f,-,sizeof(f));
  137. scanf("%d%d%d",&n,&m,&q);
  138. for(int i=;i<=n;i++)
  139. for(int j=;j<=m;j++)
  140. scanf("%d",&a[i][j]);
  141. zy[][]=-,zy[][]=;
  142. zy[][]=-,zy[][]=;
  143. for(int i=;i<=n;i++)
  144. {
  145. for(int j=;j<=m;j++)
  146. {
  147. if(!a[i][j]) continue;
  148. f2[i][j]=;
  149. for(int k=;k<=;k++)
  150. {
  151. if(check(i,j,k))
  152. {
  153. bfs1(i+zy[k][],j+zy[k][]);
  154. for(int l=;l<=;l++)
  155. {
  156. if(check(i,j,l)&&dis[i+zy[l][]][j+zy[l][]]!=dis[][])
  157. f[i][j][l][k]=dis[i+zy[l][]][j+zy[l][]]+;
  158. }
  159. }
  160. }
  161. f2[i][j]=;
  162. }
  163. }
  164.  
  165. for(int i=;i<=q;i++)
  166. {
  167. int ex,ey,sx,sy,tx,ty;
  168. scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
  169. if(tx==sx&&ty==sy)
  170. {
  171. printf("0\n");
  172. continue;
  173. }
  174. memset(dis2,0x3f,sizeof(dis2));
  175. memset(f2,,sizeof(f2));
  176. f2[sx][sy]=;
  177. bfs1(ex,ey);
  178. bool yx=;
  179. for(int j=;j<=;j++)
  180. {
  181. if(check(sx,sy,j)&&dis[sx+zy[j][]][sy+zy[j][]]!=dis[][])
  182. {
  183. yx=;
  184. dis2[sx][sy][j]=dis[sx+zy[j][]][sy+zy[j][]];
  185. }
  186. }
  187. if(!yx)
  188. {
  189. printf("-1\n");
  190. continue;
  191. }
  192. spfa(sx,sy);
  193. int ans=0x7fffffff;
  194. for(int j=;j<=;j++)
  195. ans=min(ans,dis2[tx][ty][j]);
  196. if(ans==0x7fffffff||ans==dis2[][][])
  197. {
  198. printf("-1\n");
  199. continue;
  200. }
  201. else
  202. printf("%d\n",ans);
  203. }
  204. return ;
  205. }

[NOIP2013]华容道 题解(搜索)的更多相关文章

  1. [NOIP2013]华容道 题解

    [NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ...

  2. Luogu 1979 NOIP 2013 华容道(搜索,最短路径)

    Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...

  3. LOJ2613 NOIP2013 华容道 【最短路】*

    LOJ2613 NOIP2013 华容道 LINK 这是个好题,具体题意比较麻烦可以直接看LINK中的链接 然后考虑我们可能的移动方式 首先我们需要把白块移动到需要移动块S的附近(附近四格) 然后我们 ...

  4. [CQOI2012]模拟工厂 题解(搜索+贪心)

    [CQOI2012]模拟工厂 题解(搜索+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327574 链接题目地址:洛谷P3161 BZOJ P26 ...

  5. CF912E Prime Gift题解(搜索+二分答案)

    CF912E Prime Gift题解(搜索+二分答案) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1314956 洛谷题目链接 $     $ CF题目 ...

  6. 3537. 【NOIP2013提高组day2】华容道(搜索 + 剪枝)

    Problem 给出一个类似华容道的图.\(q\)次询问,每次给你起始点,终止点,空格位置,让你求最少步数 \(n,m\le 30, q\le 500\). Soultion 一道智障搜索题. 弱智想 ...

  7. 华容道 noip2013 70分搜索

    题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...

  8. 华容道题解 NOIP2013 思路题!

    第一次发紫题题解,居然在发布前太激动,把刚写好的还没发布的题解一个Ctrl+A和Backspace全删了.(所以这是二稿) luogu题目传送门 前置: 做本题一定要有的一些思想: 1.从简思想: 模 ...

  9. NOIP2013 DAY2题解

    DAY2 T1积木大赛 传送门 题目大意:每次可以选区间[l,r]加1,最少选几次,让每个位置有 它应有的高度. 题解:O(n)扫一遍就好了.后一个比前一个的高度低,那么前一个已经把它覆盖了, 如果高 ...

随机推荐

  1. Ubuntu16.04下配置laravel

    参考 http://tecadmin.net/install-laravel-framework-on-ubuntu/# 本人亲试,完全正确 注意: Step 4 – Set Encryption K ...

  2. .Net DateTime跨时区相关问题

    项目:.Net CS结构,WCF通信,MySql存储. 场景:客户端(UTC+07:00)获取本地时间(DateTime对象)2017-01-17 15:20:12,通过WCF(http)传输至服务端 ...

  3. SQL之连接查询

    这几天忙着笔试.面试,遇到了好几个关于数据库的试题,当然只是简单的多表查询.我第一时间都是选择select...from...where...group by...having...这个结构去写的.但 ...

  4. Dec Working Note

    01 新的一个月,也是16年最后一个月,意义非凡. 那么第一天就要来点非凡的意义:提出离职. 纠结了好久,最后还是离职了,感觉是好他妈的爽,纠结什么呢. 不过今天状态不好,最近状态一直不好,上火,也没 ...

  5. Java8 的一些新特性总结

    目前Java8已经发布很多个版本了,对于Java8中的新特性虽然有各位大神进行jdk8的英文特性文档翻译,但都太官方化语言,对照几篇翻译本人对新特性文档做一下总结,以帮助我和各位不了解Java8新特性 ...

  6. Delphi访问活动目录(使用COM,活动目录Active Directory是用于Windows Server的目录服务)

    活动目录Active Directory是用于Windows Server的目录服务,它存储着网络上各种对象的有关信息,并使该信息易于管理员和用户查找及使用.Active Directory使用结构化 ...

  7. KM算法 详解+模板

    先说KM算法求二分图的最佳匹配思想,再详讲KM的实现.[KM算法求二分图的最佳匹配思想] 对于具有二部划分( V1, V2 )的加权完全二分图,其中 V1= { x1, x2, x3, ... , x ...

  8. python 参考知识点

    本笔记仅作为有编程基础的童鞋在学习python时的参考资料,不适合零基础小白,并假设在你的电脑上已经正确安装了python环境,windows下需要配置环境变量,可以在终端窗口中执行以下命令 set ...

  9. ElasticSearch学习(一):ElasticSearch介绍

    一.ElasticSearch是什么? ElasticSearch是一款非常强大的.基于Lucene的开源搜索及分析引擎,可以帮助你从海量数据中,快速找到相关的数据信息. 比如,当你在GitHub上搜 ...

  10. IM推送保障及网络优化详解(二):如何做长连接加推送组合方案

    对于移动APP来说,IM功能正变得越来越重要,它能够创建起人与人之间的连接.社交类产品中,用户与用户之间的沟通可以产生出更好的用户粘性. 在复杂的 Android 生态环境下,多种因素都会造成消息推送 ...