题目戳我

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

题解

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

所以,预处理一下???

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

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

因此,我们考虑预处理一个数组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. 用Android属性动画实现和演示迪士尼动画基本原则

    本文将介绍在Android平台上实现和演示迪士尼动画基本准则. 项目开源,GitHub: https://github.com/vhow/animation 说明: 演示动画原则的想法源自 Anima ...

  2. LeetCode - 728. Self Dividing Numbers

    A self-dividing number is a number that is divisible by every digit it contains. For example, 128 is ...

  3. python的面向对象和面向过程

    一.面向对象和面向过程的区别: a.面向过程: 1)根据业务逻辑从上到下写代码 2)开发思路是将数据和函数按照执行的逻辑顺序组织在一起 3)分开考虑数据与函数 定义性文字: 面向对象编程(Object ...

  4. 织梦使用if判断某个字段是否为空

    织梦如何使用if判断某个字段是否为空呢?我们以文章页调用文章摘要为例: 使用if语句判断摘要是否为空,如果有摘要就显示摘要模块,如果没有就不显示 {dede:field.description run ...

  5. maven常用命令介绍

    mvn 3.0.4 创建maven项目命令  mvn  archetype:generate   -DgroupId=damocles-autocredit -DartifactId=damocles ...

  6. Windows系统上Redis的安装

    Redis 安装 Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你系统 ...

  7. 解决maven项目Cannot change version of project facet Dynamic web module to 3.0

    问题描述         用Eclipse创建Maven结构的web项目的时候选择了Artifact Id为maven-artchetype-webapp,由于这个catalog比较老,用的servl ...

  8. React Native填坑之旅 -- 回归小插曲

    回归RN,非常开心啊! 在React Native 0.49.5上开发,直接遇到一个ios模拟器的问题.这个问题很简单就是Bundle URL not present. 在网上找了很多的解决方法,都不 ...

  9. 接口测试执行工具Postman:模拟请求、用例执行、断言、批量运行用例、简单持续集成

    一.接口测试-postman-模拟HTTP Requests 二.接口测试-postman-权限Authorization 三.接口测试-postman-断言Writting Test 四.接口测试- ...

  10. Android开发Toast Notifications

    Android开发Toast Notifications 关键类 Toast toast通知是一种在窗口表面弹出的消息.它只占用信息显示所需的空间,用户当前的activity仍保持可见并可交互.该通知 ...