JZYZOJ1442 [noip2013]华容道 bfs 最短路 剪枝
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 最短路 剪枝的更多相关文章
- LOJ2613 NOIP2013 华容道 【最短路】*
LOJ2613 NOIP2013 华容道 LINK 这是个好题,具体题意比较麻烦可以直接看LINK中的链接 然后考虑我们可能的移动方式 首先我们需要把白块移动到需要移动块S的附近(附近四格) 然后我们 ...
- [Luogu1979][NOIP2013]华容道(BFS+SPFA)
考虑从起点到终点的过程,一定是先将空格子移到指定格子旁边,和指定格子交换,再移到下一个指定格子要到的地方,再交换,如此反复. 于是问题分为两个部分: 1.给定两个曼哈顿距离为2的格子求最短路,BFS即 ...
- vijos1846 [NOIP2013] 华容道【最短路】
传送门:https://vijos.org/p/1983 (其实noip的题各个oj都会有的,就不贴其它传送门了) 这道题真的是,怎么说,我都不知道怎么评价了= =.果然数据量小的题怎么暴力都可以过. ...
- 洛谷 P1979 [ NOIP 2013 ] 华容道 —— bfs + 最短路
题目:https://www.luogu.org/problemnew/show/P1979 真是一道好题... 首先考虑暴力做法,应该是设 f[i][j][x][y] 记录指定棋子和空格的位置,然后 ...
- Luogu P1979 华容道(bfs+最短路)
P1979 华容道 题意 题目描述 小B最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成, 最少需要多少时间. ...
- [NOIP2013]华容道 题解
[NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ...
- [NOIP2013]华容道 题解(搜索)
[NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...
- POJ 2251 Dungeon Master (BFS最短路)
三维空间里BFS最短路 #include <iostream> #include <cstdio> #include <cstring> #include < ...
- 【bzoj5049】[Lydsy九月月赛]导航系统 并查集+双向BFS最短路
题目描述 给你一张 $n$ 个点 $m$ 条边的随机图,边权为1.$k$ 次询问两点间最短路,不连通则输出-1. 输入 第一行包含3个正整数n,m,k(2<=n<=100000,1< ...
随机推荐
- 【51NOD-0】1046 A^B Mod C
[算法]快速幂运算 [题解]快速幂的原理是把幂用二进制表示,从最低位a,次低位a2,次次低位(a2)2. #include<cstdio> long long quick_pow(long ...
- 如果你也想写个完整的 Vue 组件项目
1.一个完整的组件项目需要什么? 必要的: 组件构建方式 ( webpack / rollup 之类 ),并提供至少一个主流的输出格式 (ESModule) Demo 及 Demo 源码 文档,可以是 ...
- HDU 1284 钱币兑换问题 (dp)
题目链接 Problem Description 在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法.请你编程序计算出共有多少种兑法. Input 每行只有一个正整数N,N小于327 ...
- 【HNOI】 期望面积
[题目描述]给定n个点,求这n个点组成凸包的期望面积.保证任意三点不共线. [数据范围]n<=100. 首先我们知道凸包面积的计算为所有在凸包上相邻的点的叉积和,那么我们可以枚举两个点,然后求出 ...
- Sketch VS Photoshop
参考:http://mp.weixin.qq.com/s?__biz=MjM5NTQ5MjIyMA==&mid=217309554&idx=4&sn=4d6a5239ca813 ...
- 报错注入遇到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 ...
- 通过call_usermodehelper()在内核态执行用户程序【转】
转自:http://edsionte.com/techblog/archives/category/linux%E5%86%85%E6%A0%B8%E7%BC%96%E7%A8%8B 背景 如何在Li ...
- 浅析MongoDB用户管理
浅析MongoDB用户管理 http://www.jb51.net/article/53830.htm mongodb3.03开启认证 http://21jhf.iteye.com/blog/2216 ...
- ubuntu在vim编辑时,方向键无法正常使用
/* 如果在普通用户下. */ [frankie@localhost ~]$ sudo apt-get install vim [frankie@localhost ~]$ cd /etc/vim [ ...
- python traceback
1. Python中的异常栈跟踪 之前在做Java的时候,异常对象默认就包含stacktrace相关的信息,通过异常对象的相关方法printStackTrace()和getStackTrace()等方 ...