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初赛新题型还未公布,故会含有一些比较老的内容,敬请谅解. 约定: 若无特殊说明,本文中未知数均为整数 [表达式] 表示:在表达式成立时它的值为 ...
随机推荐
- 在C++/CLI环境下,千万不要把普通全局函数当标准C/C++的函数指针传递给native的库使用
先上一个简单代码: #include <cstdlib> #include <cstdio> // native apis extern "C" { typ ...
- 听过N次还是不会之:浏览器输入url后到底经历了什么
有没有这种场景:当你被问起某一项知识点时,你大脑里想起经常看到过这样的问题,可是具体是怎么样就是说不清楚. 好吧,我就是这样的,于是整理一下,实在记不住,以后找起来也方便. 当你在浏览器地址栏里输入一 ...
- Java的字符串操作
目录 Java的字符串操作 一.不同字符串操作的对比 1.1 C++中const修饰指针 const在星号的左边,是被指向的常量不可变 const在星号的右边,是指针的指向不可变 二. Java字符串 ...
- 非IT行业大企程序员讲述MIS系统开发案例
雪莉叹了一口气,调整了一下被汗水濡湿的刘海,然后向后靠在办公椅中,伸手在电脑键盘上输入了一些内容, 最后拿起印刷着房地产广告的扇子,边扇风边等待着. 她的工位在办公室的东侧角落,侧靠着窗.此时 ...
- OpenResty 作者章亦春访谈实录
[软件简介] OpenResty (也称为 ngx_openresty)是一个全功能的 Web 应用服务器.它打包了标准的 Nginx 核心,很多的常用的第三方模块,以及它们的大多数依赖项. 通过众多 ...
- .NET CORE命令行
目录 0. 基础命令行 1. 基础命令 2. SDK命令 3. 使用命令行创建. net Core项目 shanzm-2020年9月7日 22:00:00 0. 基础命令行 D:默认路径跳转到D盘 c ...
- 沉珂日重的Java项目 Spring真的帮到我们了吗?
开局三连图. 这是刚开始时的程序结构,虽清晰已经有混乱的前兆. 业务增加,人员增加后就会沉珂日重. 几年后,最后的模样会让使用者和维护者都很无奈. 人们喜欢把Java程序的层次结构比作建筑,实际却最像 ...
- 原生JDK网络编程- Buffer
Buffer用于和NIO通道进行交互.数据是从通道读入缓冲区,从缓冲区写入到通道中的.以写为例,应用程序都是将数据写入缓冲,再通过通道把缓冲的数据发送出去,读也是一样,数据总是先从通道读到缓冲,应用程 ...
- Docker Compose 搭建 Redis Cluster 集群环境
在前文<Docker 搭建 Redis Cluster 集群环境>中我已经教过大家如何搭建了,本文使用 Docker Compose 再带大家搭建一遍,其目的主要是为了让大家感受 Dock ...
- jmeter的用途
1.可以测接口 2.测试连数据库 3.可以进行压测 4.可部署分布式