题目描述

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

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

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

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

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

给定一个棋盘,游戏可以玩 \(q\) 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘 上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第$ i$ 次 玩的时候,空白的格子在第$ EX_i$ 行第 \(EY_i\) 列,指定的可移动棋子的初始位置为第 \(SX_i\) 行第 \(SY_i\) 列,目标位置为第 \(TX_i\) 行第 \(TY_i\) 列。

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

Input

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

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

接下来的 \(q\) 行,每行包含 \(6\) 个整数依次是 \(EX_i、EY_i、SX_i、SY_i、TX_i、TY_i\),每两个整 数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。

\(100\%\)的数据,\(1 ≤ n, m ≤ 30,q ≤ 500。\)

Output

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

Sample Input

3 4 2
0 1 1 1
0 1 1 0
0 1 0 0
3 2 1 2 2 2
1 2 2 2 3 2

Sample Output

2
-1

很显然,看到这道题的第一眼就想到了广搜。

每次,只用记录空白块以及指定块的位置,直接广搜。

然而,我们仔细算一下时间复杂度\(O(q*(n*m)^2)\)。

不能愉快的过掉此题。。。。

考虑优化,我们发现:

1.指定块能移动到指定位置当且仅当空白块在指定块边上。

2.当指定块移动时,必定是空白块到了指定块的另一边,在进行交换。

并且,这些状态的转移步数在指定块固定时可以直接广搜得到。

于是我们考虑,对那些状态进行建图,建完图后进行连边。

那么如何对这些状态进行建图呢?

之前,我们发现只有空白块在指定块的四周才有用,只有这才是有效状态。

所以,我们定义一个有效状态为:

空白块在指定块的上下左右

于是,我们就可以很方便的对一个状态进行哈希,一个状态的哈希函数为:

inline int Id(int x,int y,int cnt){
return 120*x+4*y+cnt;//x,y为指定块的所在的位置,cnt为空白块在指定块的上下左右的位置
}

定义出了哈希函数后,我们可以对两个状态进行连边,很显然,对于一个有效状态,其后续状态有四个:

为空白块在其他的三个方向,以及空白块和指定块交换(这个状态的边权是一)

于是,我们对每个状态进行广搜建图,连边。

最后,对于每个询问直接在建好的图上跑最短路即可。

代码如下

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define u64 unsigned long long
#define u32 unsigned int
#define reg register
#define Raed Read
#define debug(x) cerr<<#x<<" = "<<x<<endl;
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,G,x) for(int i=(G).Head[x]; i; i=(G).Nxt[i]) inline int Read() {
int res = 0, f = 1;
char c;
while (c = getchar(), c < 48 || c > 57)if (c == '-')f = 0;
do res = (res << 3) + (res << 1) + (c ^ 48);
while (c = getchar(), c >= 48 && c <= 57);
return f ? res : -res;
} template<class T>inline bool Min(T &a, T const&b) {
return a > b ? a = b, 1 : 0;
}
template<class T>inline bool Max(T &a, T const&b) {
return a < b ? a = b, 1 : 0;
} const int N=35,M=4505;
const int dx[4]= {1,-1,0,0},dy[4]= {0,0,1,-1}; bool MOP1; int n,m,q,A[N][N]; struct Link_list {
int Tot,Head[M],cost[M<<1],to[M<<1],Nxt[M<<1];
inline void clear(void) {
Tot=0;
memset(Head,0,sizeof Head);
}
inline void AddEdge(int a,int b,int c) {
to[++Tot]=b,cost[Tot]=c,Nxt[Tot]=Head[a],Head[a]=Tot;
}
} G; inline int Id(int x,int y,int cnt) {
return 120*x+4*y+cnt;
} struct T3Ac {
struct node {
int x,y;
} Q[N*N*N*N];
int dis[N][N];
void bfs(int x1,int y1,int x2,int y2,int cnt) {
memset(dis,0,sizeof dis);
dis[x1][y1]=1;
int L=0,R=0;
Q[++R]=(node)<%x1,y1%>;
while(L<R) {
node Now=Q[++L];
rep(i,0,3) {
int Dx=dx[i]+Now.x,Dy=dy[i]+Now.y;
if(Dx<1||Dy<1||Dx>n||Dy>m)continue;
if(Dx==x2&&Dy==y2)continue;
if(!A[Dx][Dy])continue;
if(dis[Dx][Dy])continue;
dis[Dx][Dy]=dis[Now.x][Now.y]+1;
Q[++R]=(node)<%Dx,Dy%>;
}
}
if(!(cnt^4))return;
rep(i,0,3) {
int Dx=dx[i]+x2,Dy=dy[i]+y2;
if(Dx<1||Dy<1||Dx>n||Dy>m)continue;
if(Dx==x1&&Dy==y1)continue;
if(!dis[Dx][Dy])continue;
G.AddEdge(Id(x2,y2,cnt),Id(x2,y2,i),dis[Dx][Dy]-1);
}
G.AddEdge(Id(x2,y2,cnt),Id(x1,y1,cnt^1),1);
}
int vis[M],D[M],q1[N*N*N*N];
void spfa(int x1,int y1) {
int L=0,R=0;
memset(D,63,sizeof D);
memset(vis,0,sizeof vis);
rep(i,0,3) {
int Dx=dx[i]+x1,Dy=dy[i]+y1;
if(Dx<1||Dy<1||Dx>n||Dy>m)continue;
if(!dis[Dx][Dy])continue;
D[Id(x1,y1,i)]=dis[Dx][Dy]-1,vis[Id(x1,y1,i)]=1;
q1[++R]=Id(x1,y1,i);
}
while(L<R) {
int x=q1[++L];
vis[x]=0;
erep(i,G,x) {
int y=G.to[i],z=G.cost[i];
if(D[y]>D[x]+z) {
D[y]=D[x]+z;
if(!vis[y])vis[y]=1,q1[++R]=y;
}
}
}
}
inline void solve(void) {
rep(i,1,n)rep(j,1,m)A[i][j]=Read();
rep(i,1,n)rep(j,1,m) {
if(!A[i][j])continue;
rep(k,0,3) {
int Dx=dx[k]+i,Dy=dy[k]+j;
if(A[Dx][Dy])bfs(Dx,Dy,i,j,k);
}
}
rep(i,1,q) {
int ex=Read(),ey=Read(),sx=Read(),sy=Read(),tx=Read(),ty=Read();
if(sx==tx&&sy==ty) {
puts("0");
continue;
}
bfs(ex,ey,sx,sy,4);
spfa(sx,sy);
int Ans=1e9;
rep(j,0,3)Min(Ans,D[Id(tx,ty,j)]);
if(Ans<1e9)printf("%d\n",Ans);
else puts("-1");
}
}
} P100; bool MOP2; inline void _main(void) {
n=Read(),m=Read(),q=Read();
P100.solve();
} signed main() {
#define offline1
#ifdef offline
freopen("puzzle.in", "r", stdin);
freopen("puzzle.out", "w", stdout);
_main();
fclose(stdin);
fclose(stdout);
#else
_main();
#endif
return 0;
}

noip2013day2-华容道的更多相关文章

  1. [NOIP2013]华容道

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

  2. codevs 3290 华容道(SPFA+bfs)

    codevs 3290华容道 3290 华容道 2013年NOIP全国联赛提高组 时间限制: 1 s  空间限制: 128000 KB 题目描述 Description 小 B 最近迷上了华容道,可是 ...

  3. NOIP2013 提高组day2 3 华容道 BFS

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

  4. 【NOIP2013】华容道

    看别人的代码然后被坑了一下午+一晚上,睡一觉第二天醒悟过来打表过了 果然打表才是正确的调试方法,跟踪什么的去屎(╯‵□′)╯︵┻━┻ 原题: 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成 ...

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

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

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

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

  7. 【noip】华容道

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

  8. 【NOIP2013】华容道 广搜+spfa

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

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

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

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

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

随机推荐

  1. 好多坑的升级 phpStudy 中 MySQL 版本至 5.7.17

      由于本地用的集成环境是 phpStudy 2016,没有找到升级 MySQL 版本的选项,所以自己升级一下. 从官网上下载高版本的 MySQL :https://dev.mysql.com/dow ...

  2. 1、Qt应用程序

    新建Qt Widgets Application,基类选择QWidget Qt项目特点(参考上图):头文件名与类名一样,成对出现 main.cpp代码解释如下 #include "mywid ...

  3. C++ - extern “C”含义深层探索

    C和C++函数的相互引用原文地址:http://blog.csdn.net/wfwd/archive/2006/05/30/763734.aspx=========================== ...

  4. Scrapy学习(二)、安装及项目结构

    一.安装 1.安装pywin32,下载地址:https://sourceforge.net/projects/pywin32/files/pywin32/ 我选择的是Build 221,点进去,根据自 ...

  5. rem等比例自适应手机尺寸

    方法:用sass的函数动态计算rem值 $rem : 75px;基准值 设计图是750的宽 设为$rem变量设为75,设计图是350的宽 设为$rem变量设为35,老的写法 需要用js来配合来动态改变 ...

  6. Java基础__Java中异常处理那些事

    一.Exception 类的层次 所有的异常类是从 java.lang.Exception 类继承的子类. Exception 类是 Throwable 类的子类.除了Exception类外,Thro ...

  7. spark 笔记 14: spark中的delay scheduling实现

    延迟调度算法的实现是在TaskSetManager类中的,它通过将task存放在四个不同级别的hash表里,当有可用的资源时,resourceOffer函数的参数之一(maxLocality)就是这些 ...

  8. leetcode-easy-others-190. Reverse Bits-NO

    mycode 不会... 参考: 1. 思路: 将十进制的n转换成二进制(str) -> 利用切片.反向获取不包含0b的反转后的二进制字符串 -> 补上0(共32位) 2. class S ...

  9. 【转】C++ const成员变量和成员函数(常成员函数)

    转:http://c.biancheng.net/view/2230.html 在类中,如果你不希望某些数据被修改,可以使用const关键字加以限定.const 可以用来修饰成员变量和成员函数. co ...

  10. 第八章 SpringCloud之Feign、Hystrix结合使用

    #这个章节主要是针对Hystrix的使用,因为Feign的章节在上一节已经实现了,整个代码也是在上一个章节的基础上修改的 ##################Hystrix一个简单Demo实现#### ...