题目戳我

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

题解

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

所以,预处理一下???

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

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

因此,我们考虑预处理一个数组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. [Python Study Notes]文件操作

    文件操作 对文件操作流程 打开文件,可添加filepath打开某绝对路径下的文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 # The_author = 'liu66' # -* ...

  2. 在 Mac 中安装 MySQLdb (Python mysql )

    安装环境:OS X操作系统,Python 2.7.3. MySQLdb其实包含在MySQL-python包中,因此无论下载还是在pip中search,都应该是搜寻MySQL-python. 以下将说明 ...

  3. Centos7新功能

    Centos7 单用户模式   centos7里不再有0-6启动级别,而是4个target   graphical.target  多人模式,支持图形和命令行两种登录,对应之前的3,5级别   mul ...

  4. 低版本IE内核浏览器兼容placeholder属性解决办法

    最简便的一个方法,通过js实现. <input type="text" name="username" id="username" v ...

  5. pro asp.net mvc 5笔记

    1.Ninject条件绑定方法When(predicate)WhenClassHas<T>()WhenInj ectedInto<T>()例: kernel.Bind<I ...

  6. SQL替换语句 批量修改、增加、删除字段内容

    sql替换语句,用该命令可以整批替换某字段的内容,也可以批量在原字段内容上加上或去掉字符. 命令总解:update 表的名称 set 此表要替换的字段名=REPLACE(此表要替换的字段名, '原来内 ...

  7. GCC精彩之旅_2(转)

    说明: 本文共两篇,转自GCC精彩之旅.第一篇着重介绍GCC编译一个程序的过程与优化,第二篇侧重在GCC结合GDB对代码的调试. 调试     一个功能强大的调试器不仅为程序员提供了跟踪程序执行的手段 ...

  8. crontab定时任务(centos)

    cron服务是Linux的内置服务,但它不会开机自动启动.可以用以下命令启动和停止服务: /sbin/service crond start /sbin/service crond stop /sbi ...

  9. 使用FFMPeg对视频进行处理

    FFMPeg处理视频的核心操作方式是命令,无论是在Windows上还是Linux上.那么下边就简单介绍下,常见的处理命令. 示例1:截取一张352×240尺寸大小的,格式为jpg的图片: ffmpeg ...

  10. 在Ubuntu上安装PHPStudy组件

    phpStudy for Linux (lnmp+lamp一键安装包) phpStudy Linux版&Win版同步上线 支持Apache/Nginx/Tengine/Lighttpd/IIS ...