http://172.20.6.3/Problem_Show.asp?id=1442

想到最短路的简直神了,如果我写我大概只能写一个30分的bfs。

从数据范围可以看出思路是bfs剪枝,但这里的剪枝是通过最短路的预处理实现的。

设需要移动的格子为a格子。

对求最小移动数有意义的移动只有两种,一种是空白格子的移动,一种是a格子移动到空白格子里。

可以得知要把空白格子移动到a格子旁边然后对a格子进行移动。

那么我们有了每次查找时进行的预处理1:求空白格子到a格子四周格子的最短路。

在模拟移动的过程中,可以发现a格子移动的方向是由其旁边的空白格子的位置决定的,对改变a格子移动方向有意义的步数是改变空白格子相对于a格子的方向的步数。

所以我们就有了预处理2:在查找前预处理出loc[x][y][i][j],即空白格子从格子(x,y)的i方向移动到j方向的最短路。

需要注意的是,预处理1中求最短路是不能经过a格子所在位置的,同样,其他的bfs或最短路处理也要注意格子移动对所求格子位置的改变,避免改变所求格子位置的情况。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const long long modn=;
int n,m,d;
int e[][]={};
int dis[][]={};
int an[][][]={};
int loc[][][][]={};
int vis[][][]={};
int d1[]={,,,-};
int d2[]={,-,,};
int ex,ey,sx,sy,tx,ty,ma;
struct pa{
int x;
int y,w;
};
void getit(int xx,int yy){
int x,y;
queue<pa>q;
pa z;
for(int i=;i<;i++){
z.x=xx+d1[i];
z.y=yy+d2[i];
memset(dis,,sizeof(dis));
if(e[z.x][z.y]){
dis[z.x][z.y]=;
q.push(z);
}
while(!q.empty()){
x=q.front().x;y=q.front().y;q.pop();
for(int i=;i<;i++){
z.x=x+d1[i];
z.y=y+d2[i];
if(e[z.x][z.y]&&(z.x!=xx||z.y!=yy)&&dis[z.x][z.y]==ma){
dis[z.x][z.y]=dis[x][y]+;
q.push(z);
}
}
}
for(int j=;j<;j++){
int xx1,yy1;
xx1=xx+d1[j];
yy1=yy+d2[j];
loc[xx][yy][i][j]=dis[xx1][yy1];
}
}
}
void pre(){
pa z;
queue<pa>q;
memset(dis,,sizeof(dis));
dis[ex][ey]=;
z.x=ex;
z.y=ey;
q.push(z);
int x,y;
while(!q.empty()){
x=q.front().x;y=q.front().y;q.pop();
for(int i=;i<;i++){
z.x=x+d1[i];
z.y=y+d2[i];
if(e[z.x][z.y]&&(z.x!=sx||z.y!=sy)&&dis[z.x][z.y]==ma){
dis[z.x][z.y]=dis[x][y]+;
q.push(z);
}
}
}
}
int bfs(){
if(sx==tx&&sy==ty)return ;
pre();
queue<pa>q;pa z;
memset(an,,sizeof(an));
for(int i=;i<;i++){
z.x=sx+d1[i];
z.y=sy+d2[i];
z.w=i;
if(e[z.x][z.y]&&dis[z.x][z.y]!=ma){
an[sx][sy][i]=dis[z.x][z.y];
z.x=sx;z.y=sy;
vis[sx][sy][i]=;
q.push(z);
}
}int x,y,w;
while(!q.empty()){
x=q.front().x;
y=q.front().y;
w=q.front().w;
q.pop();
for(int i=;i<;i++){
if(i==w)continue;
z.x=x;z.y=y;z.w=i;
if(e[x+d1[w]][y+d2[w]]&&an[x][y][w]+loc[x][y][w][i]<an[x][y][i]){
an[x][y][i]=an[x][y][w]+loc[x][y][w][i];
if(!vis[x][y][i]){
vis[x][y][i]=;
q.push(z);
}
}
}
z.x=x+d1[w];z.y=y+d2[w];
if(w==)z.w=;
else if(w==)z.w=;
else if(w==)z.w=;
else z.w=;
if(an[x][y][w]+<an[z.x][z.y][z.w]){
an[z.x][z.y][z.w]=an[x][y][w]+;
if(!vis[z.x][z.y][z.w]){
vis[z.x][z.y][z.w]=;
q.push(z);
}
}
vis[x][y][w]=;
}
int ans=ma;
for(int i=;i<;i++){
ans=min(ans,an[tx][ty][i]);
}
if(ans!=ma)return ans;
return -;
}
int main(){
//freopen("wtf.in","r",stdin);
scanf("%d%d%d",&n,&m,&d);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%d",&e[i][j]);
}
}memset(loc,,sizeof(loc));
ma=loc[][][][];
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
getit(i,j);
}
}
for(int i=;i<=d;i++){
scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
memset(vis,,sizeof(vis));
printf("%d\n",bfs());
}
return ;
}

JZYZOJ1442 [noip2013]华容道 bfs 最短路 剪枝的更多相关文章

  1. LOJ2613 NOIP2013 华容道 【最短路】*

    LOJ2613 NOIP2013 华容道 LINK 这是个好题,具体题意比较麻烦可以直接看LINK中的链接 然后考虑我们可能的移动方式 首先我们需要把白块移动到需要移动块S的附近(附近四格) 然后我们 ...

  2. [Luogu1979][NOIP2013]华容道(BFS+SPFA)

    考虑从起点到终点的过程,一定是先将空格子移到指定格子旁边,和指定格子交换,再移到下一个指定格子要到的地方,再交换,如此反复. 于是问题分为两个部分: 1.给定两个曼哈顿距离为2的格子求最短路,BFS即 ...

  3. vijos1846 [NOIP2013] 华容道【最短路】

    传送门:https://vijos.org/p/1983 (其实noip的题各个oj都会有的,就不贴其它传送门了) 这道题真的是,怎么说,我都不知道怎么评价了= =.果然数据量小的题怎么暴力都可以过. ...

  4. 洛谷 P1979 [ NOIP 2013 ] 华容道 —— bfs + 最短路

    题目:https://www.luogu.org/problemnew/show/P1979 真是一道好题... 首先考虑暴力做法,应该是设 f[i][j][x][y] 记录指定棋子和空格的位置,然后 ...

  5. Luogu P1979 华容道(bfs+最短路)

    P1979 华容道 题意 题目描述 小B最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成, 最少需要多少时间. ...

  6. [NOIP2013]华容道 题解

    [NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ...

  7. [NOIP2013]华容道 题解(搜索)

    [NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...

  8. POJ 2251 Dungeon Master (BFS最短路)

    三维空间里BFS最短路 #include <iostream> #include <cstdio> #include <cstring> #include < ...

  9. 【bzoj5049】[Lydsy九月月赛]导航系统 并查集+双向BFS最短路

    题目描述 给你一张 $n$ 个点 $m$ 条边的随机图,边权为1.$k$ 次询问两点间最短路,不连通则输出-1. 输入 第一行包含3个正整数n,m,k(2<=n<=100000,1< ...

随机推荐

  1. 基本控件文档-UISwitch属性---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...

  2. 牛客网刷题(纯java题型 31~60题)

    牛客网刷题(纯java题型 31~60题) 重写Override应该满足"三同一大一小"三同:方法名相同,参数列表相同,返回值相同或者子类的返回值是父类的子类(这一点是经过验证的) ...

  3. C++之编译器与链接器工作原理

    原文来自:http://blog.sina.com.cn/s/blog_5f8817250100i3oz.html 这里并没不是讨论大学课程中所学的<编译原理>,只是写一些我自己对C++编 ...

  4. C++之参数总结

    函数的形参为函数提供了已命名的局部存储空间,它是在函数的形参表中定义的,并由调用函数时传递给函数的实参初始化,而形参的 初始化与变量的初始化一样,如果形参具有非引用类型,则复制实参的值,如果形参为引用 ...

  5. sql server查看创建表的代码,表定义

    1.查看建表语句在“对象资源管理器”中找到要导出的表,选中该表并单击右键,“编写表脚本为(S)”/“CREATE到(C)”/“新查询编辑器窗口”即可查看该表的建表语句.2.导出建表语句在“对象资源管理 ...

  6. abp 调试

    概要 研究Abp(ASP.NET Boilerplate)框架有几个月了,从一遍遍的看官方文档,到现在看源码,一路走来学习了很多知识. 很多新手都很关心源码如何调试,我也是如此,在反复看Debuggi ...

  7. (转)opencv 代替caffe.io.load_image

    self.net.blobs[, , self.image_resize, self.image_resize) #image = caffe.io.load_image(image_file) im ...

  8. Scrapy爬虫:抓取大量斗图网站最新表情图片

      一:目标 第一次使用Scrapy框架遇到很多坑,坚持去搜索,修改代码就可以解决问题.这次爬取的是一个斗图网站的最新表情图片www.doutula.com/photo/list,练习使用Scrapy ...

  9. Mysql安装发生「Access denied for user ‘root’@’localhost’ (using password: NO)」错误

    参考:http://www.aipacommander.com/entry/2014/05/26/152247 mysql_secure_installation 依赖重置密码

  10. Leetcode 之Binary Tree Preorder Traversal(42)

    树的先序遍历.定义一个栈,先压入中间结点并访问,然后依次压入右.左结点并访问. vector<int> preorderTraversal(TreeNode *root) { vector ...