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. 【51NOD-0】1046 A^B Mod C

    [算法]快速幂运算 [题解]快速幂的原理是把幂用二进制表示,从最低位a,次低位a2,次次低位(a2)2. #include<cstdio> long long quick_pow(long ...

  2. 如果你也想写个完整的 Vue 组件项目

    1.一个完整的组件项目需要什么? 必要的: 组件构建方式 ( webpack / rollup 之类 ),并提供至少一个主流的输出格式 (ESModule) Demo 及 Demo 源码 文档,可以是 ...

  3. HDU 1284 钱币兑换问题 (dp)

    题目链接 Problem Description 在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法.请你编程序计算出共有多少种兑法.   Input 每行只有一个正整数N,N小于327 ...

  4. 【HNOI】 期望面积

    [题目描述]给定n个点,求这n个点组成凸包的期望面积.保证任意三点不共线. [数据范围]n<=100. 首先我们知道凸包面积的计算为所有在凸包上相邻的点的叉积和,那么我们可以枚举两个点,然后求出 ...

  5. Sketch VS Photoshop

    参考:http://mp.weixin.qq.com/s?__biz=MjM5NTQ5MjIyMA==&mid=217309554&idx=4&sn=4d6a5239ca813 ...

  6. 报错注入遇到ERROR 1242 (21000): Subquery returns more than 1 row解决方案

    我的SQL语句是这样写的. mysql> select 1,2,3 and updatexml(1,concat(1,(select user from mysql.user),1),1);ER ...

  7. 通过call_usermodehelper()在内核态执行用户程序【转】

    转自:http://edsionte.com/techblog/archives/category/linux%E5%86%85%E6%A0%B8%E7%BC%96%E7%A8%8B 背景 如何在Li ...

  8. 浅析MongoDB用户管理

    浅析MongoDB用户管理 http://www.jb51.net/article/53830.htm mongodb3.03开启认证 http://21jhf.iteye.com/blog/2216 ...

  9. ubuntu在vim编辑时,方向键无法正常使用

    /* 如果在普通用户下. */ [frankie@localhost ~]$ sudo apt-get install vim [frankie@localhost ~]$ cd /etc/vim [ ...

  10. python traceback

    1. Python中的异常栈跟踪 之前在做Java的时候,异常对象默认就包含stacktrace相关的信息,通过异常对象的相关方法printStackTrace()和getStackTrace()等方 ...