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< ...
随机推荐
- 2008 APAC local onsites C Millionaire (动态规划,离散化思想)
Problem You have been invited to the popular TV show "Would you like to be a millionaire?" ...
- HDU 2717 Catch That Cow (深搜)
题目链接 Problem Description Farmer John has been informed of the location of a fugitive cow and wants t ...
- linux 3389连接工具Rdesktop
简单使用 工作机换成战斗机了,改用ubuntu,原来的windows7上东西笔记多,还不想重装.用rdesktop来远程连接windows: sudo apt-get install rdesktop ...
- Python学习笔记 - day12 - Python操作NoSQL
NoSQL(非关系型数据库) NoSQL,指的是非关系型的数据库.NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称.用于超大规模数据的存储.(例如 ...
- Coursera课程《Machine Learning》吴恩达课堂笔记
强烈安利吴恩达老师的<Machine Learning>课程,讲得非常好懂,基本上算是无基础就可以学习的课程. 课程地址 强烈建议在线学习,而不是把视频下载下来看.视频中间可能会有一些问题 ...
- yocto 离线编译
使用yocto编译一个软件包时,一般会先在本地寻找下载好的源码包,如果不存在则根据配置从网络下载. 添加本地源码包 为了支持离线编译,添加一个包的配置文件后,需要在本地也准备好源码包. 可以先打开网络 ...
- DSP学习教程基于28335(一)
首先说明:开发环境Manjaro linux,内核5.0,滚动升级版本,随时都是最新,CCS也是最新的CCv 8 #include "DSP2833x_Device.h" // 这 ...
- 基于ARM 构架(带MMU)的copy_from_user与copy_to_user详细分析
[转自:http://blog.chinaunix.net/uid-20543672-id-3195249.html] 在学习Linux内核驱动的时候,一开始就会碰到copy_from_use ...
- Git 常用命令速查表(图文+表格)【转】
转自:http://www.jb51.net/article/55442.htm 一. Git 常用命令速查 git branch 查看本地所有分支git status 查看当前状态 git comm ...
- 64_g3
gimp-resynthesizer-2.0-6.20160601git787ee5a.fc2..> 11-Feb-2017 05:36 77650 gimp-save-for-web-0.29 ...