Description

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

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

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

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

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

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

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

Input

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

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

接下来的 q 行,每行包含 6 个整数依次是EXi、EYi、SXi、SYi、TXi、TYi,每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。

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

讲道理,这题的预处理真的不是来恶心人的吗TAT

一篇比较资磁的题解

然后有一个小技巧:用1代表上,2代表左,3代表右,4代表下,则a的反方向就是5-a。

存一存代码。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,k,ex,ey,sx,sy,tx,ty,ans;
int map[][],deep[][],dis[][][],mov[][][][];
bool d[][],in[][][];
struct node{int x,y,k;}t1,t2;
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
node move(node t,int k)
{
if(k==)t.x--;if(k==)t.y--;
if(k==)t.y++;if(k==)t.x++;
return t;
}
int bfs(node s,node t)
{
node now,to;
memset(deep,0x3f,sizeof(deep));
memset(d,,sizeof(d));
queue<node>q;q.push(s);
deep[s.x][s.y]=;d[s.x][s.y]=true;
while(!q.empty()&&!d[t.x][t.y])
{
now=q.front();q.pop();
for(int k=;k<=;k++)
{
to=move(now,k);
if(!d[to.x][to.y]&&map[to.x][to.y]==)
{
d[to.x][to.y]=true;q.push(to);
deep[to.x][to.y]=deep[now.x][now.y]+;
}
}
}
return deep[t.x][t.y];
}
void init()
{
memset(mov,0x3f,sizeof(mov));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
if(map[i][j]==)continue;
map[i][j]=;
for(int k=;k<=;k++)
for(int l=;l<=;l++)
{
if(l<k){mov[i][j][k][l]=mov[i][j][l][k];continue;}
t1=move((node){i,j,k},k);t2=move((node){i,j,l},l);
if(map[t1.x][t1.y]==||map[t2.x][t2.y]==)continue;
mov[i][j][k][l]=bfs(t1,t2)+;
}
map[i][j]=;
}
}
void spfa(node s,node t)
{
ans=inf;
if(s.x==t.x&&s.y==t.y){ans=;return;}
if(map[s.x][s.y]==||map[t.x][t.y]==)return;
node now,to;
memset(dis,0x3f,sizeof(dis));
memset(in,,sizeof(in));
queue<node>q;
map[s.x][s.y]=;
for(int i=;i<=;i++)
{
q.push((node){s.x,s.y,i});
in[s.x][s.y][i]=true;
dis[s.x][s.y][i]=bfs((node){ex,ey,},move(s,i));
}
map[s.x][s.y]=;
while(!q.empty())
{
now=q.front();q.pop();
in[now.x][now.y][now.k]=false;
for(int i=;i<=;i++)
{
to=move(now,i);to.k=-i;
if(dis[now.x][now.y][now.k]+mov[now.x][now.y][now.k][i]<dis[to.x][to.y][-i])
{
dis[to.x][to.y][-i]=dis[now.x][now.y][now.k]+mov[now.x][now.y][now.k][i];
if(!in[to.x][to.y][to.k])q.push(to),in[to.x][to.y][to.k]=true;
}
}
}
for(int i=;i<=;i++)ans=min(ans,dis[t.x][t.y][i]);
}
int main()
{
n=read();m=read();k=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
map[i][j]=read();
init();
for(int i=;i<=k;i++)
{
ex=read();ey=read();sx=read();sy=read();tx=read();ty=read();
spfa((node){sx,sy,},(node){tx,ty,});
if(ans==inf)printf("-1\n");
else printf("%d\n",ans);
}
return ;
}

【noip 2014】提高组Day2T3.华容道的更多相关文章

  1. NOIP 2014 提高组 题解

    NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法 ...

  2. noip 2014 提高组初赛

    noip 2014 提高组初赛 一. TCP协议属于哪一层协议( ) A. 应用层 B. 传输层 C. 网络层 D. 数据链路层 B TCP(传输控制协议) 若有变量int a; float: x, ...

  3. noip 2014 提高组 Day 2

    1.无线网络发射器选址 这道题数据范围很小,就直接暴力枚举就好了.为了提高速度,就从每个有公共场所的点枚举周围在(x,y)放无线网路发射器可以增加的公共场所数量,加到一个数组里.所有公共场所都处理完了 ...

  4. NOIP 2014 提高组 Day1

    期望得分:100+100+50=250 实际得分:100+100+50=250 此次NOIP  ZJ省一分数线:500,SD:345 https://www.luogu.org/problem/lis ...

  5. 洛谷P1979 [NOIP2013提高组Day2T3]华容道

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

  6. NOIP 2014 提高组 Day2

    期望得分:100+60+30=190 实际得分:70+60+30=160 https://www.luogu.org/problem/lists?name=&orderitem=pid& ...

  7. NOIP 2008提高组第三题题解by rLq

    啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...

  8. [NOIp 1998 提高组]Probelm 2 连接多位数【2011百度实习生笔试题】

    /*====================================================================== [NOIp 1998 提高组]Probelm 2 连接 ...

  9. NOIP 2001 提高组 题解

    NOIP 2001 提高组 题解 No 1. 一元三次方程求解 https://vijos.org/p/1116 看见有人认真推导了求解公式,然后猥琐暴力过的同学们在一边偷笑~~~ 数据小 暴力枚举即 ...

随机推荐

  1. Opennebula常用命令

    查看虚拟机状态信息: [oneadmin@localhost /]$ onevm list 查看虚拟机配置: [oneadmin@localhost /]$ onevm show 25 启动虚拟机: ...

  2. 为什么分布式一定要有redis?

    为什么分布式一定要有redis? 孤独烟 架构师小秘圈 昨天 作者:孤独烟 来自:http://rjzheng.cnblogs.com/ 1.为什么使用redis   分析:博主觉得在项目中使用red ...

  3. 洛谷P1848 书架

    好,我一直以为书架是splay,然后发现还有个优化DP的书架.妃的书架 蓝书和PPT上面都讲了,应该比较经典吧. 题意: 有n个物品,每个都有宽,高. 把它们分成若干段,使得每段的最大值的总和最小.且 ...

  4. 洛谷P3185 分裂游戏

    解:这个毒瘤...... 我们首先发现每一堆的个数对操作不产生影响,每个操作都是针对单个石子的. 所以等价于每个石子都是一个独立的游戏.把它们异或起来作为sg函数值即可. 单个石子的sg值,直接暴力计 ...

  5. A1099. Build A Binary Search Tree

    A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...

  6. 【BZOJ3289】Mato的文件管理 莫队+树状数组

    题目大意:给定一个长度为 N 的序列,M 个询问,每次询问区间逆序对的个数. 题解:用树状数组加速答案转移. 代码如下 #include <bits/stdc++.h> #define f ...

  7. PHP生成四角图片

    <?php /** 圆角 $radius = 100; $img = imagecreatetruecolor($radius, $radius); // 创建一个正方形的图像 $bgcolor ...

  8. bzoj2938 AC自动机 + 拓扑排序找环

    https://www.lydsy.com/JudgeOnline/problem.php?id=2938 题意:给出N个01病毒序列,询问是否存在一个无限长的串不存在病毒序列 正常来说,想要寻找一个 ...

  9. bzoj1106 树状数组

    https://www.lydsy.com/JudgeOnline/problem.php?id=1106 一个叫做立方体大作战的游戏风靡整个Byteotia.这个游戏的规则是相当复杂的,所以我们只介 ...

  10. 集成学习算法汇总----Boosting和Bagging(推荐AAA)

     sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...