题目戳我

懒得粘贴题目了。。就这要凑合一下吧。。。

题解

反正棋盘的状态不会变的。。。

所以,预处理一下???

恩,如果一个棋子要移动到某个目标位置的话,

可以看成只有空格和这个子要动呀(其他的有区别吗??)

因此,我们考虑预处理一个数组move[i][j][k][l]

表示在(i,j)位置,空格在k方向的时候,移动到l方向的最短距离

至于方向是哪边就自己定义一下吧。。

那么,这个预处理,直接跑BFS就行了。。。

最后对于每一个状态求解,

只要先让空格到达移动的棋子旁边,在利用move数组跑SPFA就行了(很显然的呀。。。)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
using namespace std;
#define INF 1000000000
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int N,M,Q;
int d[5][2]={0,1,0,-1,1,0,-1,0,0,0};
int g[50][50],far[50][50],Ans[50][50][4];
bool vis[50][50];
bool Vis[50][50][4];
int dis[50][50][4][4];
int Tx,Ty,Sx,Sy,Ex,Ey;
struct Node
{
int x,y,st;
};
struct Dalao
{
int x,y,fr;
};
inline void BFS(int X,int Y,int dd)
{
queue<Node> Q;while(!Q.empty())Q.pop();
memset(vis,0,sizeof(vis));
for(int i=1;i<=N;++i)
for(int j=1;j<=M;++j)
far[i][j]=INF;
Q.push((Node){X+d[dd][0],Y+d[dd][1],0});
vis[X][Y]=true;
vis[X+d[dd][0]][Y+d[dd][1]]=true;
far[X][Y]=0;
if(dd==4)
vis[Sx][Sy]=true;
while(!Q.empty())
{
Node now=Q.front();
int st=now.st,xx=now.x,yy=now.y;Q.pop();
for(int i=0;i<4;++i)
{
int x=xx+d[i][0],y=yy+d[i][1];
if(!g[x][y])continue;
if(vis[x][y])continue;
vis[x][y]=true;
far[x][y]=st+1;
Q.push((Node){x,y,st+1});
}
}
}
void BFS(int Sx,int Sy)
{
queue<Dalao> Q;while(!Q.empty())Q.pop();
memset(Vis,0,sizeof(Vis));
for(int i=1;i<=N;++i)
for(int j=1;j<=M;++j)
for(int k=0;k<4;++k)
Ans[i][j][k]=INF;
for(int i=0;i<4;++i)
{
int x=Sx+d[i][0],y=Sy+d[i][1];
if(!g[x][y]||far[x][y]==INF)continue;
Q.push((Dalao){x,y,i^1});
Ans[x][y][i^1]=far[x][y]+1;
Vis[x][y][i^1]=true;
}
while(!Q.empty())
{
Dalao now=Q.front();Q.pop();
int xx=now.x,yy=now.y,fr=now.fr;
for(int i=0;i<4;++i)
{
int x=xx+d[i][0],y=yy+d[i][1];
if(!g[x][y])continue;
if(Ans[x][y][i^1]>Ans[xx][yy][fr]+dis[xx][yy][fr][i]+1)
{
Ans[x][y][i^1]=Ans[xx][yy][fr]+dis[xx][yy][fr][i]+1;
if(!Vis[x][y][i^1])
{
Q.push((Dalao){x,y,i^1});
Vis[x][y][i^1]=true;
}
}
}
Vis[xx][yy][fr]=false;
}
}
int main()
{
N=read();M=read();Q=read();
for(int i=1;i<=N;++i)
for(int j=1;j<=M;++j)
g[i][j]=read();
for(int i=1;i<=N;++i)
for(int j=1;j<=M;++j)
for(int k=0;k<4;++k)
if(g[i+d[k][0]][j+d[k][1]])
{
BFS(i,j,k);
for(int gg=0;gg<4;++gg)
{
if(gg==k)
{
dis[i][j][k][k]=INF;
continue;
}
if(g[i+d[gg][0]][j+d[gg][1]])
dis[i][j][k][gg]=far[i+d[gg][0]][j+d[gg][1]];
else
dis[i][j][k][gg]=INF;
}
}
while(Q--)
{
Ex=read(),Ey=read();//空格
Sx=read(),Sy=read();//起点
Tx=read(),Ty=read();//终点
if(Sx==Tx&&Sy==Ty)
{
printf("0\n");
continue;
}
BFS(Ex,Ey,4);
BFS(Sx,Sy);
int ans=INF;
for(int i=0;i<4;++i)ans=min(Ans[Tx][Ty][i],ans);
printf("%d\n",ans==INF?-1:ans);
}
return 0;
}

【NOIP2013】华容道(最短路)的更多相关文章

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

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

  2. [NOIP2013]华容道 题解

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

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

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

  4. NOIP2013 华容道 (棋盘建图+spfa最短路)

    #include <cstdio> #include <algorithm> #include <cstring> #include <queue> # ...

  5. JZYZOJ1442 [noip2013]华容道 bfs 最短路 剪枝

    http://172.20.6.3/Problem_Show.asp?id=1442 想到最短路的简直神了,如果我写我大概只能写一个30分的bfs. 从数据范围可以看出思路是bfs剪枝,但这里的剪枝是 ...

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

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

  7. loj2613 「NOIP2013」华容道[最短路]

    感觉和以前做过的一个推箱子很像,都是可以用bfs解决的,而且都是手玩出结论. 因为起始棋子肯定是要和空格交换的,所以第一件事是先把空格移到棋子旁边.然后讨论怎么设计搜索状态.由于和推箱子实在太像了,所 ...

  8. [NOIP2013]华容道

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

  9. NOIP2013华容道 大爆搜

    预处理出每个点周围四个点互相到达的最短路,再在整个图上跑SPFA,要记录路径 #include<cstdio> #include<cstring> #include<io ...

  10. luogu P1979 [NOIP2013] 华容道

    传送门 这道题中,棋子的移动是要移动到空格上去,所以空格要在棋子旁边才能移动棋子;而棋子移动的方向由空格决定 所以我们可以记三维状态\(di_{i,j,k}\),表示状态为棋子在\((i,j)\),空 ...

随机推荐

  1. 从Myeclipse到Intelj Idea

    前言:经历了从eclipse到Myeclipse的时间,大学时候用Eclipse,开始工作的时候选择Myeclipse,都能体会到Java的IDE的先进和高明之处,直到最近,公司项目采git和Grad ...

  2. maven的安装与配置使用

     一  maven的安装 1 在镜像(https://mirrors.tuna.tsinghua.edu.cn/apache/)中下载指定的版本(注意,Maven 版本与IDE版本应保持匹配). 2 ...

  3. linux中/bin和/sbin和/usr/bin和/usr/sbin

    首先先解释一下bin和sbin的意思: 1.bin:为任何用户都可以使用的指令 2.sbin:(super bin)也就是只有超级管理员才能使用的指令 /usr    UNIX Software Re ...

  4. PHP对象和接口抽象类注意事项

    Php 的对象的实现: 注:对象名称最好以对象名.class.php来进行命名. 1. 对于静态类的成员不能使用$this->这个来调用其静态类的成员和函数,应该使用self::成员或者方法来进 ...

  5. PHP不使用array_merge函数实现一维数组合并

    function array_mer() { $arrays = func_get_args(); //获取当前函数中传递进来的所有参数,也就是所有一维数组 // echo '<pre>' ...

  6. 在Centos环境下安装兼容Apache2.4高版本SVN服务

    在阿里云Centos环境下,搭建PHP运行环境,PHP选择了php7版本,Mysql选择了5.7版本,Apache选择了2.4版本,在搭建SVN版本控制服务过程中出现了不兼容问题,当前环境下Apach ...

  7. 五子棋的判断输赢规则 -- java编程(简单优化完整版)

    五子棋的判断输赢规则代码 -- 完整优化版 一.前言 之前浏览过很多网上的方法,但总找不到比较完整,也get不到其他大神的思路,就直接画图分析,分析了之后就有了如下的代码,当然还想到更加优化的一种,只 ...

  8. nyoj 取石子(七) 环形博弈

    手推前几个可以知道规律:n>2时是P态,n<=2时是N态. 注意:石子拿去后,剩下的石子是分散的. AC代码 #include <cstdio> #include <cm ...

  9. nyoj137 取石子(三) 楼教主男人八题之一

    思路:一堆时,N态.两堆时,当两堆数量相同,P态,不同为N态.三堆时,先手可以变成两堆一样的,必胜N态. 此时可以总结规律:堆数为偶数可能且石子数都是两两相同的,为P态.分析四堆时,当四堆中两两数量一 ...

  10. 【视频教程】一步步将AppBox升级到Pro版

    本系列教程分为上中下三部分,通过视频的形式讲解如何将基于FineUI(开源版)的AppBox v6.0一步一步升级FineUIPro(基础版). [视频教程]一步步将AppBox升级到Pro版(上)主 ...