NOIP提高组2013 D2T3 【华容道】
某王 老师给我们考了一场noip2013的真题。。。心态爆炸!
题目大意:
有一个n*m的棋盘,每个格子上都有一个棋子,有些格子上的棋子能够移动(可移动的棋子是固定的),棋盘中有一个格子是空的,仍何可移动的棋子都能够与空格子交换位置。现在有q个询问,每个询问给出kx,ky,sx,sy,ex,ey,分别为空白格子的坐标,要你移动的棋子,目标位置。对于每个询问,要求你求出,把要求你移动的棋子移到目标位置最少移动几次。
思路分析:
首先讲一下暴力做法吧。
这应该大家都能想得到,BFS嘛,记录要求我们移动的棋子(暂且记作1号格子)当前的位置和空白格子(记作2号格子)的位置,当2移动到1旁边时,那么1就可以与2交换位置。
而正解就是基于暴力展开的。。。
我们发现其实当2移动到1旁边后,便产生了很多无用的状态,我们只需要知道2在1周围的几个状态就够了,因为1格子进行移动时,无非就是和它周围的几个格子交换位置,而交换位置后2仍然在1的周围,所以我们只需要知道2在从1周围的4个格子走到另一个格子的最小花费即可。
我们记一个三元组(x,y,k)其中x,y表示1号棋子的坐标,k表示2号棋子相对1号棋子的位置(0表示在1的上面,1表示在1的右边,2表示在1的左边,3表示在1的下面),当然一心想要偷懒的我粗暴地把三元组压成了一个数,是这么压的(x,y,k)=k*n*m+(x-1)*m+y,嗯,免得你们看不懂代码。。。
那么根据我们先前讲的,设计两种连边:
1、可以在(x,y,0~3)与(x,y,0~3)之间设计一条长度为空白格子从一个位置(x,y的上下左右)走到另一个位置(x,y的上下左右)的最小花费。
2、在(x,y,k)与(x+dx[k],y+dy[k],3-k)之间连一条边,其意义便是1号格子与2号格子交换了位置。(现在知道我这么设计方向的(shi)用(wei)心(le)良(tou)苦(lan)了吧)
先把连边预处理出来,然后我们只要第一次计算出初始位置的2号格子移动到1号格子的上下左右的最小花费(可以BFS暴力做)之后,跑一边Dijkstra就完事儿了!
代码实现:
type
hehe=record
dist,id:longint;
end;
haha=record
x,y,dist:longint;
end;
var
next,vet,dist:array[1..200000]of longint;
f:array[1..2000000]of hehe;
a:array[1..90000]of haha;
d,fir,visit:array[1..48000]of longint;
map,vis:array[-50..50,-50..50]of longint;
dx,dy:array[0..3]of longint;
sx,sy,ex,ey,kx,ky,xx,yy,n,m,q,i,j,ii,jj,tot,weight,x,y,oo,cost,ans,z,x1,x2,y1,y2:longint;
procedure add(x,y,z:longint);
begin
inc(tot);
next[tot]:=fir[x];
fir[x]:=tot;
vet[tot]:=y;
dist[tot]:=z;
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x) else exit(y);
end;
procedure swap(x,y:longint);
var
t:hehe;
begin
t:=f[x]; f[x]:=f[y]; f[y]:=t;
end;
procedure up(x:longint);
begin
if x=1 then exit;
if f[x].dist<f[x div 2].dist then begin swap(x,x div 2); up(x div 2); end;
end;
procedure down(x:longint);
var
k:longint;
begin
if x*2>n then exit;
k:=min(f[x*2].dist,f[x*2+1].dist);
if f[x].dist>k then
if k=f[x*2].dist then begin swap(x,x*2); down(x*2); end
else begin swap(x,x*2+1); down(x*2+1); end;
end;
procedure push(x,id:longint);
begin
inc(weight);
f[weight].dist:=x;
f[weight].id:=id;
up(weight);
end;
procedure pop;
begin
x:=f[1].id;
f[1].dist:=f[weight].dist;
f[1].id:=f[weight].id;
f[weight].dist:=oo;
f[weight].id:=oo;
dec(weight);
down(1);
end;
procedure dijkstra;
var
y,i:longint;
begin
fillchar(visit,sizeof(visit),0);
while weight>0 do
begin
pop;
if x>4800 then continue;
if d[x]>=oo then break;
if visit[x]=1 then continue;
visit[x]:=1;
i:=fir[x];
while i<>0 do
begin
y:=vet[i];
if (dist[i]<oo)and(d[y]>d[x]+dist[i]) then
begin d[y]:=d[x]+dist[i]; push(d[y],y); end;
i:=next[i];
end;
end;
end;
function bfs(nx,ny,x1,y1,x2,y2:longint):longint;
var
head,tail,dist,xx,yy,x,y,i:longint;
begin
if map[x1,y1]+map[x2,y2]<>2 then exit(oo);
if (x1=x2)and(y1=y2) then exit(0);
fillchar(vis,sizeof(vis),0);
head:=0; tail:=1; bfs:=maxlongint;
a[1].x:=x1; a[1].y:=y1; a[1].dist:=0; vis[x1,y1]:=1;
while head<>tail do
begin
inc(head);
x:=a[head].x; y:=a[head].y; dist:=a[head].dist;
for i:=0 to 3 do
begin
xx:=x+dx[i]; yy:=y+dy[i];
if ((xx<>nx)or(yy<>ny))and(map[xx,yy]=1)and(vis[xx,yy]=0) then
begin
inc(tail);
a[tail].x:=xx; a[tail].y:=yy; a[tail].dist:=dist+1;
vis[xx,yy]:=1;
if (xx=x2)and(yy=y2) then exit(dist+1);
end;
end;
end;
end;
begin
read(n,m,q);
for i:=1 to n do
for j:=1 to m do
read(map[i,j]);
dx[0]:=-1; dy[1]:=1; dy[2]:=-1; dx[3]:=1;
for i:=1 to n do
for j:=1 to m do
if map[i,j]=1 then
for ii:=0 to 3 do
begin
x1:=i+dx[ii]; y1:=j+dy[ii]; x2:=i; y2:=j;
if map[x1,y1]+map[x2,y2]=2 then
begin
add(ii*n*m+(x2-1)*m+y2,(3-ii)*n*m+(x1-1)*m+y1,1);
end;
for jj:=0 to 3 do
begin
x2:=i+dx[jj]; y2:=j+dy[jj];
if (ii<>jj)and(map[x1,y1]+map[x2,y2]=2) then
begin
cost:=bfs(i,j,x1,y1,x2,y2);
add(ii*n*m+(i-1)*m+j,jj*n*m+(i-1)*m+j,cost);
end;
end;
end;
while q>0 do
begin
read(kx,ky,sx,sy,ex,ey);
fillchar(d,sizeof(d),$1f);
oo:=d[1];
fillchar(f,sizeof(f),$1f);
weight:=0;
if (sx=ex)and(sy=ey) then
begin
writeln(0);
dec(q);
continue;
end;
for i:=0 to 3 do
begin
x:=sx+dx[i]; y:=sy+dy[i];
if map[x,y]=1 then
begin
d[i*n*m+(sx-1)*m+sy]:=bfs(sx,sy,kx,ky,x,y);
push(d[i*n*m+(sx-1)*m+sy],i*n*m+(sx-1)*m+sy);
end;
end;
dijkstra;
ans:=oo;
for i:=0 to 3 do
begin
z:=i*n*m+(ex-1)*m+ey;
if d[z]<=ans then ans:=d[z];
end;
if ans=oo then writeln(-1) else writeln(ans);
dec(q);
end;
end.
NOIP提高组2013 D2T3 【华容道】的更多相关文章
- NOIP提高组 2013货车运输
觉得题目水的离开 不屑的大佬请离开 不会图论的请离开 ……. 感谢您贡献的访问量 ————————————华丽的分割线———————————— 题面: 题目描述 A 国有 n 座城市,编号从 1 到 ...
- 题解 【luoguP1967 NOIp提高组2013 货车运输】
题目链接 题解 题意 给你一个无向图,求两个点之间的一条路径,使路径上的最小值最大 算法:Kruskal最大生成树+倍增lca 分析 首先容易知道,答案一定在该图的最大生成树上 之后问题便转换成了树上 ...
- 洛谷P1966 火柴排队[NOIP提高组2013]
我确信我应该是做过这道题……就当再写一遍好了. 贪心思想,一番证明得出a和b数组中最小对最小,次小对次小……时解最优.那么先处理出a,b之间的对应关系,然后按照该关系求a或者b的逆序对数量就是答案 / ...
- NOIP提高组2016 D2T3 【愤怒的小鸟】
貌似还没有写过状压DP的题目,嗯,刚好今天考了,就拿出来写一写吧. 题目大意: 额,比较懒,这次就不写了... 思路分析: 先教大家一种判断题目是不是状压DP的方法吧. 很简单,那就是--看数据范围! ...
- NOIP提高组2004 合并果子题解
NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...
- 计蒜客 NOIP 提高组模拟竞赛第一试 补记
计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...
- 1043 方格取数 2000 noip 提高组
1043 方格取数 2000 noip 提高组 题目描述 Description 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样 ...
- [NOIP提高组2018]货币系统
[TOC] 题目名称:货币系统 来源:2018年NOIP提高组 链接 博客链接 CSDN 洛谷博客 洛谷题解 题目链接 LibreOJ(2951) 洛谷(P5020) 大视野在线评测(1425) 题目 ...
- NOIP提高组初赛难题总结
NOIP提高组初赛难题总结 注:笔者开始写本文章时noip初赛新题型还未公布,故会含有一些比较老的内容,敬请谅解. 约定: 若无特殊说明,本文中未知数均为整数 [表达式] 表示:在表达式成立时它的值为 ...
随机推荐
- springboot @valid与@validated的参数校验使用总结
好久没在这平台写博客了,最近整理了这东西,先给出总结 // @Valid只能用在controller,@Validated可以用在其他被spring管理的类上 // @Valid可以加在成员变量上(本 ...
- 【jmespath】—3. 进阶 Object Projections
继续,来看Object Projections. 一.Object Projections 上面说的是列表投影,只适用于列表.那么对于json对象,可以用对象投影. 投影最终返回的仍然是个列表,只不过 ...
- layui 表单验证汇总
1 表单自带校验 lay-verify:是表单验证的关键字有以下值供选择: required 必填项phone 手机号email 邮箱date 日期url 链接identity 身份证number 数 ...
- Activiti7 流程变量(UEL-Value方式)
需求:请假天数大于3天走总经理审批,小于等于3天直接走人事 画图 因为IDEA不展示那个线上的东西,所以截屏自己写的,还有就是我感觉IDEA画图挺坑的,之前画了好几遍,一部署就报错,很奇怪 /** * ...
- 实验 1:Mininet 源码安装和可视化拓扑工具
实验 1:Mininet 源码安装和可视化拓扑工具 一.实验目的 掌握 Mininet 的源码安装方法和 miniedit 可视化拓扑生成工具. 二.实验任务 使用源码安装 Mininet 的 2.3 ...
- 在CentOs7上yum安装redis
在开始安装步骤之前,先把我的CentOs和redis版本号列出来: # 系统/软件 版本号 1 CentOS7 CentOS Linux release 7.2.1511 (Core) 2 redis ...
- Jenkins下Vue自动部署(一)
1,服务器上安装docker http://www.runoob.com/docker/ubuntu-docker-install.html?tdsourcetag=s_pctim_aiomsg 2, ...
- synchronized底层是怎么实现的?
前言 面试的时候有被问到,synchronized底层是怎么实现的,回答的比较浅,面试官也不是太满意,所以觉得要好好总结一下,啃啃这个硬骨头. synchronized使用场景 我们在使用synchr ...
- 【吴恩达课程使用】anaconda (python 3.7) win10安装 tensorflow 1.8 cpu版
[吴恩达课程使用]anaconda (python 3.7) win10安装 tensorflow 1.8 目前tensorflow是只支持到python3.6的,anaconda最新版本已经到pyt ...
- 什么是Lambda架构
一.Lambda架构需求 Lambda架构背后的需求是由于MR架构的延迟问题.MR虽然实现了分布式.可扩展数据处理系统的目的,但是在处理数据时延迟比较严重.实际上如果内存和CPU足够强大,MR也可以实 ...