我想动某个点的话,一定要先把空白点移动到这个点旁边,然后调换这个点和空白点,一直重复

那么,我们就可以记一些状态(x,y,s) (s={0,1},{0,-1},{1,0},{-1,0}),表示我要动的点在(x,y),然后空白点在(x+s.x,y+s.y)

这样的话我们就可以建图:$(x,y,s)-1->(x+s.x,y+s.y,s^{-1})$ (s^{-1}表示一个相反的方向,比如如果s是右边的话,那它就是左边)

$(x,y,s)-C(x,y,s+s.x,y+s.y,x+i.x,y+i.y)->(x,y,i)$ 其中,C(a,b,c,d,e,f)表示我目前这个点在(a,b),空白点在(c,d),要把空白点挪到(e,f)的最小步数,而且挪的过程中不能经过(a,b)(要不然会把要动的那个点换走)

这样的话,就可以一边bfs算出C的值,一边跑最短路了。

然而复杂度$O(q*(mn)^2)$,过不去。

考虑预处理出C,直接做显然不行($mn^3$),但其实我们要用到C的情况,都是空白点在要处理的点的旁边的,那它就可以压缩成(x,y,s,tx,ty),是900*4*900的。

当然,一开始我们的空白点和要做的点并没有在一起,只要再单独bfs一下,先把空白点挪到它边上就可以了。

要注意有起始点和目标点相同的情况,要判掉。

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define pa2 pair<int,Node>
#define ll long long
using namespace std;
const int maxn=; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Node{
int x,y,s;
Node (int x1,int x2,int x3){x=x1,y=x2,s=x3;}
};
int f[maxn][maxn],N,M,Q,dis[maxn][maxn][][maxn][maxn],dis2[maxn][maxn][];
int step[][]={{,},{,-},{,},{-,}};
bool can[maxn][maxn],flag[maxn][maxn],flag2[maxn][maxn][];
queue<pa > q;
priority_queue<pa2,vector<pa2>,greater<pa2> > q2; bool operator < (Node a,Node b){return a.x<b.x;} int bfs1(int a,int b,int c,int x0,int y0){
memset(flag,,sizeof(flag));
while(!q.empty()) q.pop();q.push(make_pair(x0,y0));
dis[a][b][c][x0][y0]=;
while(!q.empty()){
int x=q.front().first,y=q.front().second;q.pop();
for(int i=;i<=;i++){
int xx=x+step[i][],yy=y+step[i][];
if(!flag[xx][yy]&&can[xx][yy]){
q.push(make_pair(xx,yy));
dis[a][b][c][xx][yy]=dis[a][b][c][x][y]+;
}
}flag[x][y]=;
}
} int dijkstra(int ex,int ey,int sx,int sy,int tx,int ty){
if(sx==tx&&sy==ty) return ;
memset(dis2,-,sizeof(dis2));memset(flag2,,sizeof(flag2));
while(!q2.empty()) q2.pop();
can[sx][sy]=;memset(dis[][][],-,sizeof(dis[][][]));
bfs1(,,,ex,ey);
for(int i=;i<=;i++){
int xx=sx+step[i][],yy=sy+step[i][];
if(dis[][][][xx][yy]!=-){
dis2[xx][yy][i^]=dis[][][][xx][yy]+;
q2.push(make_pair(dis2[xx][yy][i^],Node(xx,yy,i^)));
}
}can[sx][sy]=;
while(!q2.empty()){
Node p=q2.top().second;q2.pop();if(flag2[p.x][p.y][p.s]) continue;
for(int i=;i<=;i++){
int xx=p.x+step[i][],yy=p.y+step[i][];
if(dis[p.x][p.y][p.s][xx][yy]!=-){
if(dis2[xx][yy][i^]==-||dis2[xx][yy][i^]>dis[p.x][p.y][p.s][xx][yy]+dis2[p.x][p.y][p.s]+){
dis2[xx][yy][i^]=dis[p.x][p.y][p.s][xx][yy]+dis2[p.x][p.y][p.s]+;
q2.push(make_pair(dis2[xx][yy][i^],Node(xx,yy,i^)));
}
}
}flag2[p.x][p.y][p.s]=;
}int re=-;
for(int i=;i<=;i++){
if(dis2[tx][ty][i]==-) continue;
if(re==-) re=dis2[tx][ty][i];
else re=min(re,dis2[tx][ty][i]);
}return re;
} int main(){
int i,j,k;
N=rd(),M=rd();Q=rd();
for(i=;i<=N;i++){
for(j=;j<=M;j++) can[i][j]=rd();
}
memset(dis,-,sizeof(dis));
for(i=;i<=N;i++){
for(j=;j<=M;j++){
if(!can[i][j]) continue;can[i][j]=;
for(k=;k<=;k++){
int ii=i+step[k][],jj=j+step[k][];
if(can[ii][jj]) bfs1(i,j,k,ii,jj);
}can[i][j]=;
}
}
for(i=;i<=Q;i++){
int x1=rd(),x2=rd(),x3=rd(),x4=rd(),x5=rd(),x6=rd();
printf("%d\n",dijkstra(x1,x2,x3,x4,x5,x6));
}
return ;
}

luogu1979 华容道 (dijkstra+bfs)的更多相关文章

  1. SCU-4527 NightMare2(Dijkstra+BFS) !!!错误题解!!!

    错解警告!!! 描述 可怜的RunningPhoton又做噩梦了..但是这次跟上次不大一样,虽然他又被困在迷宫里,又被装上了一个定时炸弹,但是值得高兴的是,他发现他身边有数不清的财宝,所以他如果能带着 ...

  2. CDOJ 1964 命运石之门【最短路径Dijkstra/BFS】

    给定数字n,m(1<=n,m<=500000) 将n变为n*2花费2,将n变为n-3花费3,要求过程中所有数字都在[1,500000]区间内. 求将n变为m的最少花费 思路:建图 将每个数 ...

  3. URAL 1837. Isenbaev&#39;s Number (map + Dijkstra || BFS)

    1837. Isenbaev's Number Time limit: 0.5 second Memory limit: 64 MB Vladislav Isenbaev is a two-time ...

  4. NOIP2013华容道(BFS+乱搞)

    n<=30 * m<=30 的地图上,0表示墙壁,1表示可以放箱子的空地.q<=500次询问,每次问:当空地上唯一没有放箱子的空格子在(ex,ey)时,把位于(sx,sy)的箱子移动 ...

  5. [luogu1979] 华容道

    题面 ​ 先讲点无关的,这道题是真的恶心... ​ 好了,第一眼看到这道题,肯定是准备暴搜的,但是想了一想,省选难度的题目不可能一上来就让你暴搜吧,于是开启了无穷无尽的分析,我们不妨设指定棋子叫做移动 ...

  6. lightoj 1099【dijkstra/BFS】

    题意: 求 1-N 的第二长路,一条路可以重复走 if two or more shortest paths exist, the second-shortest path is the one wh ...

  7. bzoj P1979 华容道【bfs+spfa】

    调死我了-- 首先观察移动方式,需要移动的格子每次移动到相邻格子,一定是先把空白格子挪过去,所以我们得到一种做法,就是bfs预处理出每一个格子的四联通格子之间的空白格子移动距离建边,注意这个移动是不能 ...

  8. hdu1548 奇怪的电梯 dfs dijkstra bfs都可以,在此奉上dfs

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/5706/ 简单的规定深度进行搜索,代码如下: #include<bits/stdc++.h> usin ...

  9. [题解+总结]NOIP2010-2015后四题汇总

    1.前言 正式开始的第一周的任务--把NOIP2010至NOIP2015的所有D1/2的T2/3写出暴力.共22题. 暴力顾名思义,用简单粗暴的方式解题,不以正常的思路思考.能够较好的保证正确性,但是 ...

随机推荐

  1. NOIp2018停课刷题记录

    Preface 老叶说了高中停课但是初中不停的消息后我就为争取民主献出一份力量 其实就是和老师申请了下让我们HW的三个人听课结果真停了 那么还是珍惜这次机会好好提升下自己吧不然就\(AFO\)了 Li ...

  2. 介绍HTTP协议的传输过程

    1.HTTP是面向事物的应用层协议,它使用TCP连接进行可靠传输,服务器默认监听在80端口 2.服务流程 从协议执行过程来说,当浏览器要访问www服务器时,首先要对服务器进行域名解析(DNS协议).一 ...

  3. 聊聊Zookeeper应用场景、架构设计、选主机制

    Zookeeper作为一个分布式协调系统提供了一项基本服务:分布式锁服务,分布式锁是分布式协调技术实现的核心内容.像配置管理.任务分发.组服务.分布式消息队列.分布式通知/协调等,这些应用实际上都是基 ...

  4. 来不及说什么了,Python 运维开发剁手价仅剩最后 2 天

    51reboot 运维开发又双叒叕的搞活动了—— Python 运维开发 18 天训练营课程, 剁手价1299 最后2天 上课方式:网络直播/面授(仅限北京) DAY1 - DAY4 Python3 ...

  5. kvm虚拟化管理平台WebVirtMgr部署-完整记录(3)

    继下面三篇文章完成了kvm虚拟化管理平台webvirtmgr环境的部署安装:kvm虚拟化管理平台WebVirtMgr部署-虚拟化环境安装-完整记录(0)kvm虚拟化管理平台WebVirtMgr部署-完 ...

  6. C. Party Lemonade

    链接 [http://codeforces.com/group/1EzrFFyOc0/contest/913/problem/C] 分析 看代码,巧妙的贪心 代码 #include<bits/s ...

  7. 2-Twenty Fourth Scrum Meeting-20151230

    前言 因为服务器关闭,我们的开发项目也遭遇停滞一个星期.与网站开发负责人员协商之后,29号开放服务器.我们的项目也能够继续下去.比规定的开发时间(截止为2015/12/29)推迟. 事项安排 1.开发 ...

  8. Linux内核分析——ELF文件格式分析

    ELF文件(目标文件)格式主要三种: 1)可重定向文件:文件保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享目标文件.(目标文件或者静态库文件,即linux通常后缀为 ...

  9. OSGB数据压缩

    OSGB数据输出时压缩数据大小,采用如下设置 osgDB::writeNodeFile(*osgbNode, "xxx/xxxx.osgb", new osgDB::Options ...

  10. SE Springer小组之《Spring音乐播放器》需求分析说明书一

    软件需求说明书 软件需求说明书的编制是为了使用户和软件开发者双方对该软件的初始规定有一个共同的理解, 使之成为整个开发工作的基础. 1 引言 1.1编写目的 使用户对该软件的初始规定有一个理解,也使软 ...