LOJ2613 NOIP2013 华容道 【最短路】*
LOJ2613 NOIP2013 华容道
这是个好题,具体题意比较麻烦可以直接看LINK中的链接
然后考虑我们可能的移动方式
首先我们需要把白块移动到需要移动块S的附近(附近四格)
然后我们就可以考虑怎么对S进行移动
- 操作一:把S和白块互换位置
- 操作二:把白块从S的一个方向移动到另一方向(方便交换位置)
第一种操作的代价是1很显然,后一种操作我们每次移动的最小代价是可以预处理的
然后我们就可以定义状态x,y,dir表示S在(x,y)且白块在S的dir方向上
我们就只需要考虑在状态之间进行转移,用spfa就够了
#include<bits/stdc++.h>
using namespace std;
#define N 40
#define INF 0x3f3f3f3f
int mx[]={,,,-};
int my[]={,-,,};
int mv[N][N][][];
int dp[N][N][];
bool inq[N][N][];
int g[N][N],dis[N][N];
int n,m,q;
int ex,ey,sx,sy,tx,ty;
struct Node1{int x,y;};
struct Node2{int x,y,dir;};
bool check_in(int x,int y){return (x>&&x<=n&&y>&&y<=m)&&g[x][y];}
void bfs1(int x,int y,int dir){
if(!check_in(x+mx[dir],y+my[dir]))return;
static queue<Node1> q;
memset(dis,0x3f,sizeof(dis));
dis[x][y]=-;
dis[x+mx[dir]][y+my[dir]]=;
q.push((Node1){x+mx[dir],y+my[dir]});
while(!q.empty()){
Node1 now=q.front();q.pop();
for(int i=;i<;i++){
int nx=now.x+mx[i];
int ny=now.y+my[i];
if(!check_in(nx,ny))continue;
if(dis[nx][ny]>dis[now.x][now.y]+){
dis[nx][ny]=dis[now.x][now.y]+;
q.push((Node1){nx,ny});
}
}
}
for(int i=;i<;i++){
int nx=x+mx[i];
int ny=y+my[i];
if(check_in(nx,ny))mv[x][y][dir][i]=dis[nx][ny];
}
}
void bfs2(){
memset(dis,0x3f,sizeof(dis));
static queue<Node1> q;
dis[ex][ey]=;
dis[sx][sy]=-;
q.push((Node1){ex,ey});
while(!q.empty()){
Node1 now=q.front();q.pop();
for(int i=;i<;i++){
int nx=now.x+mx[i];
int ny=now.y+my[i];
if(!check_in(nx,ny))continue;
if(dis[nx][ny]>dis[now.x][now.y]+){
dis[nx][ny]=dis[now.x][now.y]+;
q.push((Node1){nx,ny});
}
}
}
}
#define NOW now.x][now.y][now.dir
int spfa(){
memset(dp,0x3f,sizeof(dp));
memset(inq,,sizeof(inq));
static queue<Node2> nq;
for(int i=;i<;i++){
int nx=sx+mx[i];
int ny=sy+my[i];
if((!check_in(nx,ny))||dis[sx+mx[i]][sy+my[i]]==INF)continue;
dp[sx][sy][i]=dis[sx+mx[i]][sy+my[i]];
nq.push((Node2){sx,sy,i});
inq[sx][sy][i]=;
}
while(!nq.empty()){
Node2 now=nq.front();nq.pop();
inq[NOW]=;
for(int i=;i<;i++)
if(dp[now.x][now.y][i]>dp[NOW]+mv[NOW][i]){
dp[now.x][now.y][i]=dp[NOW]+mv[NOW][i];
if(!inq[now.x][now.y][i]){
inq[now.x][now.y][i]=;
nq.push((Node2){now.x,now.y,i});
}
}
int nx=now.x+mx[now.dir];
int ny=now.y+my[now.dir];
if(dp[nx][ny][now.dir^]>dp[NOW]+){
dp[nx][ny][now.dir^]=dp[NOW]+;
if(!inq[nx][ny][now.dir^]){
inq[nx][ny][now.dir^]=;
nq.push((Node2){nx,ny,now.dir^});
}
}
}
int ans=INF;
for(int i=;i<;i++)ans=min(ans,dp[tx][ty][i]);
if(ans==INF)ans=-;
return ans;
}
int main(){
memset(mv,0x3f,sizeof(mv));
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)scanf("%d",&g[i][j]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)if(g[i][j])
for(int k=;k<;k++)bfs1(i,j,k);
while(q--){
scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
bfs2();
if(sx==tx&&sy==ty)printf("0\n");
else printf("%d\n",spfa());
}
return ;
}
LOJ2613 NOIP2013 华容道 【最短路】*的更多相关文章
- [NOIP2013]华容道 题解
[NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ...
- [NOIP2013]华容道 题解(搜索)
[NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...
- loj2613 「NOIP2013」华容道[最短路]
感觉和以前做过的一个推箱子很像,都是可以用bfs解决的,而且都是手玩出结论. 因为起始棋子肯定是要和空格交换的,所以第一件事是先把空格移到棋子旁边.然后讨论怎么设计搜索状态.由于和推箱子实在太像了,所 ...
- NOIP2013 华容道 (棋盘建图+spfa最短路)
#include <cstdio> #include <algorithm> #include <cstring> #include <queue> # ...
- JZYZOJ1442 [noip2013]华容道 bfs 最短路 剪枝
http://172.20.6.3/Problem_Show.asp?id=1442 想到最短路的简直神了,如果我写我大概只能写一个30分的bfs. 从数据范围可以看出思路是bfs剪枝,但这里的剪枝是 ...
- vijos1846 [NOIP2013] 华容道【最短路】
传送门:https://vijos.org/p/1983 (其实noip的题各个oj都会有的,就不贴其它传送门了) 这道题真的是,怎么说,我都不知道怎么评价了= =.果然数据量小的题怎么暴力都可以过. ...
- [NOIP2013]华容道
1.题面 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间.小 B 玩的华容道与经典 ...
- NOIP2013华容道 大爆搜
预处理出每个点周围四个点互相到达的最短路,再在整个图上跑SPFA,要记录路径 #include<cstdio> #include<cstring> #include<io ...
- luogu P1979 [NOIP2013] 华容道
传送门 这道题中,棋子的移动是要移动到空格上去,所以空格要在棋子旁边才能移动棋子;而棋子移动的方向由空格决定 所以我们可以记三维状态\(di_{i,j,k}\),表示状态为棋子在\((i,j)\),空 ...
随机推荐
- mysql中索引利用情况(explain用法)
使用explain查看,如下 1.首先创建表test,语句如下 create table test(a int,b varchar(10),c varchar(10)); 2.在表中的a,b都创建索引 ...
- 使用idea引入注解@SpringBootApplication报错Cannot resolve symbol 'SpringBootApplication'
我在使用idea时,在类上使用注解@SpringBootApplication,但是一直报错. Cannot resolve symbol 'SpringBootApplication' 网络上有很多 ...
- php5权限控制修饰符,interface和abstract
1.public:public表明该数据成员.成员函数是对所有用户开放的,所有用户都可以直接进行调用 2.private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直 ...
- 20.并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解
1. ArrayBlockingQueue简介 在多线程编程过程中,为了业务解耦和架构设计,经常会使用并发容器用于存储多线程间的共享数据,这样不仅可以保证线程安全,还可以简化各个线程操作.例如在“生产 ...
- torch Tensor学习:切片操作
torch Tensor学习:切片操作 torch Tensor Slice 一直使用的是matlab处理矩阵,想从matlab转到lua+torch上,然而在matrix处理上遇到了好多类型不匹配问 ...
- EASYUI 1.4版 combobox firefox 下不支持中文检索的问题
easyui 的combobox 在IE下面输入中文,可以自动实现筛选和检索的功能,但是在firefox下面不可以. 于是查了一些资料,发现原来是浏览器对于中文输入法的处理问题,对于chrome 和 ...
- Highcharts 树状图(Treemap)
Highcharts 树状图(Treemap) 树状图 series 配置 设置 series 的 type 属性为 treemap ,series.type 描述了数据列类型.默认值为 " ...
- Java复习5.面向对象
Java 复习5面向对象知识 20131004 前言: 前几天整理了C++中的面向对象的知识,学习Java语言,当然最重要的就是面向对象的知识,因为可以说Java是最正宗的面向对象语言,相比C++,更 ...
- 二十二、utl_inaddr(用于取得局域网或Internet环境中的主机名和IP地址)
1.概述 作用:用于取得局域网或Internet环境中的主机名和IP地址. 2.包的组成 1).get_host_name作用:用于取得指定IP地址所对应的主机名语法:utl_inaddr.get_h ...
- 三、dbms_pipe(类似UNIX系统的管道)
1.概述 说明:Oracle管道类似UNIX系统的管道,但不采用OS机制实现,管道信息被缓存到SGA中,当关闭例程时会丢失管道信息,建立公用管道所有数据库用户都可访问,私有管道只能由建立这访问.作用: ...