【noip 2014】提高组Day2T3.华容道
Description
小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。
小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:
1.在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;
2.有些棋子是固定的,有些棋子则是可以移动的;
3.任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。 游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。
给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第EXi行EYi列,指定的可移动棋子的初始位置为第SXi行第SYi 列,目标位置为第TXi 行第TYi列。
假设小 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.华容道的更多相关文章
- NOIP 2014 提高组 题解
NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法 ...
- noip 2014 提高组初赛
noip 2014 提高组初赛 一. TCP协议属于哪一层协议( ) A. 应用层 B. 传输层 C. 网络层 D. 数据链路层 B TCP(传输控制协议) 若有变量int a; float: x, ...
- noip 2014 提高组 Day 2
1.无线网络发射器选址 这道题数据范围很小,就直接暴力枚举就好了.为了提高速度,就从每个有公共场所的点枚举周围在(x,y)放无线网路发射器可以增加的公共场所数量,加到一个数组里.所有公共场所都处理完了 ...
- NOIP 2014 提高组 Day1
期望得分:100+100+50=250 实际得分:100+100+50=250 此次NOIP ZJ省一分数线:500,SD:345 https://www.luogu.org/problem/lis ...
- 洛谷P1979 [NOIP2013提高组Day2T3]华容道
P1979 华容道 题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少 ...
- NOIP 2014 提高组 Day2
期望得分:100+60+30=190 实际得分:70+60+30=160 https://www.luogu.org/problem/lists?name=&orderitem=pid& ...
- NOIP 2008提高组第三题题解by rLq
啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...
- [NOIp 1998 提高组]Probelm 2 连接多位数【2011百度实习生笔试题】
/*====================================================================== [NOIp 1998 提高组]Probelm 2 连接 ...
- NOIP 2001 提高组 题解
NOIP 2001 提高组 题解 No 1. 一元三次方程求解 https://vijos.org/p/1116 看见有人认真推导了求解公式,然后猥琐暴力过的同学们在一边偷笑~~~ 数据小 暴力枚举即 ...
随机推荐
- [HNOI2010]物品调度
题目描述 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置,从0到n-1依次编号,一开始0号位置空,其它的位置i上有编号为i的盒子.Lostm ...
- NOI2010能量采集(数学)
栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量.在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起. 栋栋的植物种得非常整齐,一共有n列,每 ...
- 【lua】lua安装学习
Lua 是用标准C语言编写并以源代码形式开放的一种轻量小巧的脚本语言,设计目的是为了嵌入应用程序中,为应用程序提供灵活的扩展和定制功能. lua官网 http://www.lua.org/ 安装lua ...
- Hadoop集群的构建和安装
1.安装Java $ yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel 上述命令默认安装位置/usr/lib/jvm/java-1. ...
- Servlet -- 重定向
重定向的两种方式: 1: protected void doGet(HttpServletRequest request, HttpServletResponse response) throws S ...
- P1637 三元上升子序列
thair 好,这个naive的东西因为只有三元,很好求解.只要把每个数之前小的L[i]与之后大的R[i]求一下即可. 求两次逆序对即可.那么答案便是∑(L[i]*R[i]); 对于更高元的,胡雨菲写 ...
- MD5加密解密类(asp.net)&使用MD5过时处理
加密类 #region ========加密======== /// <summary> /// 加密 /// </summary> /// <param name=&q ...
- java抽象类和抽象方法
首先应该明确一点的是,抽象方法必须定义在抽象类中. 先看一个抽象类的定义: public abstract class Animal { public abstract void eat(); pub ...
- bzoj1875 边点互换+矩乘
https://www.lydsy.com/JudgeOnline/problem.php?id=1875 题意 HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走 ...
- CodeForces160D 最小生成树 + dfs
https://cn.vjudge.net/problem/26727/origin 题目大意: 给一个带权的无向图,保证没有自环和重边. 由于最小生成树不唯一,因此你需要确定每一条边是以下三种情况哪 ...