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初赛新题型还未公布,故会含有一些比较老的内容,敬请谅解. 约定: 若无特殊说明,本文中未知数均为整数 [表达式] 表示:在表达式成立时它的值为 ...
随机推荐
- [译]如何在ASP.NET Core中实现面向切面编程(AOP)
原文地址:ASPECT ORIENTED PROGRAMMING USING PROXIES IN ASP.NET CORE 原文作者:ZANID HAYTAM 译文地址:如何在ASP.NET Cor ...
- vue 页面首次加载缓慢原因及解决方案
第一次打包vue的项目部署到服务器,发现首次加载特别的缓慢要几十秒才加载出来,完全没有在本地开发环境上那么流畅. 主要原因是页面在打包后没有进行相关的配置导致资源文件特别大,一次想要全部加载完成回特别 ...
- 01vue.config.js
const path = require('path'); module.exports = { // 基本路径 publicPath: process.env.NODE_ENV === 'pro ...
- OpenvSwitch系列之六 vlan隔离
局域网游戏代表:红色警戒 Open vSwitch系列之一 Open vSwitch诞生 Open vSwitch系列之二 安装指定版本ovs Open vSwitch系列之三 ovs-vsctl命令 ...
- 官网安装Python包太慢?教你三种下载安装方式-PiP、conda、轮子,教你三种Pytorch的下载安装方式,保证你再也不用出现Error
上一期我们介绍了CUDA下载安装以及其总结,这一期教大家如何在Anaconda中使用CUDA来进行加速.神经网络依赖cuDNN的下载安装,以及下载和安装Pytorch-GPU安装包的三种方式(cond ...
- -1>1?! unsigned int的世界不简单
编程语言提供了很多的基本数据类型,比如char,int,float,double等等.在C和C++的世界中,还有一种类型,叫做无符号数据,修饰符位unsigned,比如今天要说的unsigned in ...
- 原生 Java 客户端进行消息通信
原生 Java 客户端进行消息通信 Direct 交换器 DirectProducer:direct类型交换器的生产者 NormalConsumer:普通的消费者 MulitBindConsumer: ...
- 哦!这该死的 C 语言
前言 C 语言是一门抽象的.面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可替代的作用,可以说 C 语言是编程的基础,也就是说,不管你学习任何语言,都应该把 C 语言放在首 ...
- 发现新世界:神级浏览器插件TamperMonkey(暴力猴)
由于谷歌浏览器各种受限 于是我就先使用火狐浏览器尝试此插件 步骤非常简单. 1.在火狐浏览器内打开如下网址:https://addons.mozilla.org/zh-CN/firefox/addon ...
- 初识ABP vNext(10):ABP设置管理
Tips:本篇已加入系列文章阅读目录,可点击查看更多相关文章. 目录 前言 开始 定义设置 使用设置 最后 前言 上一篇介绍了ABP模块化开发的基本步骤,完成了一个简单的文件上传功能.通常的模块都有一 ...