描述

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

小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:

  1. 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;

  2. 有些棋子是固定的,有些棋子则是可以移动的;

  3. 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。 游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。

给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第 EX_iEX​i​​ 行第 EY_iEY​i​​ 列,指定的可移动棋子的初始位置为第 SX_iSX​i​​ 行第 SY_iSY​i​​ 列,目标位置为第 TX_iTX​i​​ 行第 TY_iTY​i​​ 列。

假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。

格式

输入格式

第一行有 3 个整数,每两个整数之间用一个空格隔开,依次表示 n、m 和 q;

接下来的 n 行描述一个 n*m 的棋盘,每行有 m 个整数,每两个整数之间用一个空格隔开,每个整数描述棋盘上一个格子的状态,0 表示该格子上的棋子是固定的,1 表示该格子上的棋子可以移动或者该格子是空白的。

接下来的 q 行,每行包含 6 个整数依次是 EX_iEX​i​​、EY_iEY​i​​、SX_iSX​i​​、SY_iSY​i​​、TX_iTX​i​​、TY_iTY​i​​,每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。

输出格式

输出有 q 行,每行包含 1 个整数,表示每次游戏所需要的最少时间,如果某次游戏无法完成目标则输出−1。

样例1

样例输入1

  1. 3 4 2
  2. 0 1 1 1
  3. 0 1 1 0
  4. 0 1 0 0
  5. 3 2 1 2 2 2
  6. 1 2 2 2 3 2

样例输出1

  1. 2
  2. -1

限制

每个测试点1s。

提示

###样例说明

棋盘上划叉的格子是固定的,红色格子是目标位置,圆圈表示棋子,其中绿色圆圈表示目标棋子。

  1. 第一次游戏,空白格子的初始位置是 (3, 2)(图中空白所示),游戏的目标是将初始位置在(1, 2)上的棋子(图中绿色圆圈所代表的棋子)移动到目标位置(2, 2)(图中红色的格子)上。

    移动过程如下:

  2. 第二次游戏,空白格子的初始位置是(1, 2)(图中空白所示),游戏的目标是将初始位置在(2, 2)上的棋子(图中绿色圆圈所示)移动到目标位置 (3, 2)上。

    要将指定块移入目标位置,必须先将空白块移入目标位置,空白块要移动到目标位置,必然是从位置(2,2)上与当前图中目标位置上的棋子交换位置,之后能与空白块交换位置的只有当前图中目标位置上的那个棋子,因此目标棋子永远无法走到它的目标位置,游戏无法完成。

###数据范围

对于 30%的数据,1 ≤ n, m ≤ 10,q = 1; 
对于 60%的数据,1 ≤ n, m ≤ 30,q ≤ 10; 
对于 100%的数据,1 ≤ n, m ≤ 30,q ≤ 500。

来源

NOIP 2013 提高组 day 2


  首先可以考虑全盘爆搜,让空白方块到处乱跑,状态要记录空白方块的位置和目标棋子的位置,所以状态总数为n2m2,时间复杂度为O(n2m2q).

  然后来想想优化,当空白方块跑到目标棋子周围时,再到处瞎跑没什么意义而且多个询问棋盘不会改变,所以呢,可以考虑预处理一下当目标棋子的位置为(i, j)时,空白方块在目标棋子a方向时移到b方向最少要的步数。花费一个O(n2m2)的时间去跑nm次bfs。

  这有什么用呢?我们先把空白棋子移到目标棋子周围然后就可以跑spfa了,spfa除了记录目标棋子的位置再记录一下空白棋子在哪个方向,转移的时候方向相反,这个距离就可以用之前预处理的结果了。这样总时间复杂度为O(n2m2 + qn2 + kqn2),其中k为spfa的常数。

Code

  1. #include<iostream>
  2. #include<fstream>
  3. #include<sstream>
  4. #include<string>
  5. #include<cstdio>
  6. #include<cstdlib>
  7. #include<cstring>
  8. #include<ctime>
  9. #include<cmath>
  10. #include<algorithm>
  11. #include<cctype>
  12. #include<vector>
  13. #include<stack>
  14. #include<set>
  15. #include<map>
  16. #include<queue>
  17. #ifndef WIN32
  18. #define Auto "%lld"
  19. #else
  20. #define Auto "%I64d"
  21. #endif
  22. using namespace std;
  23. typedef bool boolean;
  24. #define inf 0x3fffffff
  25. #define smin(a, b) (a) = min((a), (b))
  26. #define smax(a, b) (a) = max((a), (b))
  27.  
  28. template<typename T>
  29. class Matrix {
  30. public:
  31. T* p;
  32. int col, line;
  33. Matrix():p(NULL), col(), line() { }
  34. Matrix(int line, int col):line(line), col(col) {
  35. p = new T[(const int)(line * col)];
  36. }
  37.  
  38. T* operator [] (int pos) {
  39. return p + pos * col;
  40. }
  41. };
  42.  
  43. typedef class Point {
  44. public:
  45. int x;
  46. int y;
  47. Point(int x = , int y = ):x(x), y(y) { }
  48. }Point;
  49.  
  50. ifstream fin("puzzle.in");
  51. ofstream fout("puzzle.out");
  52.  
  53. int n, m, q;
  54. Matrix<boolean> walkable;
  55. int dis[][][][];
  56.  
  57. inline void init() {
  58. fin >> n >> m >> q;
  59. walkable = Matrix<boolean>(n, m);
  60. for(int i = ; i < n; i++)
  61. for(int j = , x; j < m; j++) {
  62. fin >> x;
  63. if(x) walkable[i][j] = true;
  64. else walkable[i][j] = false;
  65. }
  66. }
  67.  
  68. const int mov[][] = {{, -, , }, {, , , -}};
  69.  
  70. boolean exceeded(int x, int y) {
  71. if(x < || x >= n) return true;
  72. if(y < || y >= m) return true;
  73. return false;
  74. }
  75.  
  76. int dep[][][][];
  77. queue<Point> que;
  78. queue<Point> que1;
  79.  
  80. boolean vis1[][];
  81. int dep1[][];
  82. inline int bfs1(Point s, Point t, Point g) {
  83. if(s.x == t.x && s.y == t.y) return ;
  84. memset(vis1, false, sizeof(vis1));
  85. dep1[s.x][s.y] = ;
  86. vis1[s.x][s.y] = true;
  87. que.push(s);
  88. while(!que.empty()) {
  89. Point e = que.front();
  90. que.pop();
  91. for(int i = ; i < ; i++) {
  92. Point eu(e.x + mov[][i], e.y + mov[][i]);
  93. if(exceeded(eu.x, eu.y)) continue;
  94. if(!walkable[eu.x][eu.y]) continue;
  95. if(vis1[eu.x][eu.y]) continue;
  96. if(eu.x == g.x && eu.y == g.y) continue;
  97. dep1[eu.x][eu.y] = dep1[e.x][e.y] + ;
  98. if(eu.x == t.x && eu.y == t.y) {
  99. while(!que.empty()) que.pop();
  100. return dep1[eu.x][eu.y];
  101. }
  102. vis1[eu.x][eu.y] = true;
  103. que.push(eu);
  104. }
  105. }
  106. return -;
  107. }
  108.  
  109. inline void init_dis() {
  110. for(int i = ; i < n; i++)
  111. for(int j = ; j < m; j++)
  112. for(int p = ; p < ; p++) {
  113. Point w(i + mov[][p], j + mov[][p]);
  114. for(int q = ; q < ; q++) {
  115. Point t(i + mov[][q], j + mov[][q]);
  116. if(exceeded(w.x, w.y) || exceeded(t.x, t.y)) dis[i][j][p][q] = -;
  117. else if(!walkable[w.x][w.y] || !walkable[i][j] || !walkable[t.x][t.y]) dis[i][j][p][q] = -;
  118. else if(p == q) dis[i][j][p][q] = ;
  119. else dis[i][j][p][q] = bfs1(w, t, Point(i, j));
  120. }
  121. }
  122. }
  123.  
  124. boolean vis2[][][];
  125. int f[][][];
  126. queue<int> que2;
  127. inline int spfa(Point s, Point t, Point w) {
  128. memset(vis2, false, sizeof(vis2));
  129. memset(f, 0x7f, sizeof(f));
  130. for(int i = ; i < ; i++) {
  131. Point e(s.x + mov[][i], s.y + mov[][i]);
  132. if(exceeded(e.x, e.y)) continue;
  133. if(!walkable[e.x][e.y]) continue;
  134. f[i][s.x][s.y] = bfs1(Point(w.x, w.y), e, Point(s.x, s.y));
  135. if(f[i][s.x][s.y] == -) f[i][s.x][s.y] = 0x7f7f7f7f;
  136. }
  137. for(int i = ; i < ; i++) {
  138. que.push(s);
  139. que2.push(i);
  140. }
  141. while(!que.empty()) {
  142. Point e = que.front();
  143. int ed = que2.front();
  144. que.pop();
  145. que2.pop();
  146. vis2[ed][e.x][e.y] = false;
  147. for(int i = ; i < ; i++) {
  148. Point eu(e.x + mov[][i], e.y + mov[][i]);
  149. int eud = i ^ ;
  150. if(exceeded(eu.x, eu.y)) continue;
  151. if(!walkable[eu.x][eu.y]) continue;
  152. if(dis[e.x][e.y][ed][i] == -) continue;
  153. if(f[ed][e.x][e.y] + dis[e.x][e.y][ed][i] + < f[eud][eu.x][eu.y]) {
  154. f[eud][eu.x][eu.y] = f[ed][e.x][e.y] + dis[e.x][e.y][ed][i] + ;
  155. if(!vis2[eud][eu.x][eu.y]) {
  156. vis2[eud][eu.x][eu.y] = true;
  157. que.push(eu);
  158. que2.push(eud);
  159. }
  160. }
  161. }
  162. }
  163. int ret = inf;
  164. for(int i = ; i < ; i++)
  165. smin(ret, f[i][t.x][t.y]);
  166. if(ret == inf) return -;
  167. return ret;
  168. }
  169.  
  170. int res = inf;
  171. inline void solve() {
  172. int wx, wy, sx, sy, tx, ty;
  173. while(q--) {
  174. res = inf;
  175. fin >> wx >> wy >> sx >> sy >> tx >> ty;
  176. wx--, wy--, sx--, sy--, tx--, ty--;
  177. if(sx == tx && sy == ty) {
  178. fout << "" << endl;
  179. continue;
  180. }
  181. fout << spfa(Point(sx, sy), Point(tx, ty), Point(wx, wy)) << endl;
  182. }
  183. }
  184.  
  185. int main() {
  186. init();
  187. init_dis();
  188. solve();
  189. return ;
  190. }

NOIP 华容道的更多相关文章

  1. 搜索(另类状态BFS):NOIP 华容道

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

  2. P1979 [NOIP]华容道

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

  3. 【NOIP 2013 DAY2 T3】 华容道(spfa)

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

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

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

  5. 【CodeVS 3290】【NOIP 2013】华容道

    http://codevs.cn/problem/3290/ 据说2013年的noip非常难,但Purpleslz学长还是AK了.能A掉这道题真心orz. 设状态$(i,j,k)$表示目标棋子在$(i ...

  6. 【noip】华容道

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

  7. 【noip 2014】提高组Day2T3.华容道

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

  8. 一道搜索题【2013 noip提高组 DAY2 t3】华容道

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

  9. 华容道 [NOIP 2013]

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

随机推荐

  1. JQUERY中各个ajax函数

    1.$(selecter).load()     --- load() 方法从服务器加载数据,并把返回的数据放入被选元素中 2.$.get(url,callback()) 3.$.post(url,d ...

  2. Chart控件的使用实例

    ChartTest.aspx: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind=&quo ...

  3. you

    抑制幽门螺旋杆菌: 1.西兰花 鲜嫩的西兰花蔬菜,含有一种物质叫异硫氰酸酯,这种物质就是幽门螺杆菌的 " 天敌 ",可达到百分百抑制的作用,甚至还有医生给了它一个最强天然抗生素的称 ...

  4. windows使用方法

    1:截图搜索英文单词:snipping tool 2: 修改语言,搜索language 3:关闭fn键,按键 fn+esc(fnlock).  就可以将fn关闭和开启.

  5. KMP(http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2772)

    #include <stdio.h>#include <string.h>#include <stdlib.h>char a[1000001],b[1000001] ...

  6. 软件包管理:rpm命令管理-包命名与依赖性

    rpm包的管理主要有两种方法:一种是rpm命令管理另一种是yum在线管理 注意软件包没有扩展名,写上只是为了好看,便于识别而已. 注意区别包名,包全名.之所以要区分,就是因为有些命令十分挑剔,需要跟正 ...

  7. c语言的字符串拷贝函数的精简

    #include <stdio.h>#include <string.h>void str_cpy(char * to, char *from){    while ((*to ...

  8. Filter—过滤器和拦截器的区别

    1.首先要明确什么是拦截器.什么是过滤器 1.1 什么是拦截器: 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加 ...

  9. SVA描述(一)

    SystemVerilog Assertion(SVA):是一种描述性的语言,可以很容易的描述时序相关的情况,所以主要用在协议检查和协议覆盖.SVA在systemverilog仿真器中的 调度区间在R ...

  10. FRM-92095: Oracle Jnitiator version too low – please install version 1.1.8.2 or higher

    打开EBS,系统报:FRM-92095: Oracle JInitiator 版本太旧. 请安装版本1.1.8.2或更高版本 (英文的错误信息是:FRM-92095: Oracle JInitiato ...