【NOIP2013】华容道(最短路)
题目戳我
懒得粘贴题目了。。就这要凑合一下吧。。。
题解
反正棋盘的状态不会变的。。。
所以,预处理一下???
恩,如果一个棋子要移动到某个目标位置的话,
可以看成只有空格和这个子要动呀(其他的有区别吗??)
因此,我们考虑预处理一个数组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】华容道(最短路)的更多相关文章
- LOJ2613 NOIP2013 华容道 【最短路】*
LOJ2613 NOIP2013 华容道 LINK 这是个好题,具体题意比较麻烦可以直接看LINK中的链接 然后考虑我们可能的移动方式 首先我们需要把白块移动到需要移动块S的附近(附近四格) 然后我们 ...
- [NOIP2013]华容道 题解
[NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ...
- [NOIP2013]华容道 题解(搜索)
[NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...
- NOIP2013 华容道 (棋盘建图+spfa最短路)
#include <cstdio> #include <algorithm> #include <cstring> #include <queue> # ...
- JZYZOJ1442 [noip2013]华容道 bfs 最短路 剪枝
http://172.20.6.3/Problem_Show.asp?id=1442 想到最短路的简直神了,如果我写我大概只能写一个30分的bfs. 从数据范围可以看出思路是bfs剪枝,但这里的剪枝是 ...
- vijos1846 [NOIP2013] 华容道【最短路】
传送门:https://vijos.org/p/1983 (其实noip的题各个oj都会有的,就不贴其它传送门了) 这道题真的是,怎么说,我都不知道怎么评价了= =.果然数据量小的题怎么暴力都可以过. ...
- loj2613 「NOIP2013」华容道[最短路]
感觉和以前做过的一个推箱子很像,都是可以用bfs解决的,而且都是手玩出结论. 因为起始棋子肯定是要和空格交换的,所以第一件事是先把空格移到棋子旁边.然后讨论怎么设计搜索状态.由于和推箱子实在太像了,所 ...
- [NOIP2013]华容道
1.题面 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间.小 B 玩的华容道与经典 ...
- NOIP2013华容道 大爆搜
预处理出每个点周围四个点互相到达的最短路,再在整个图上跑SPFA,要记录路径 #include<cstdio> #include<cstring> #include<io ...
- luogu P1979 [NOIP2013] 华容道
传送门 这道题中,棋子的移动是要移动到空格上去,所以空格要在棋子旁边才能移动棋子;而棋子移动的方向由空格决定 所以我们可以记三维状态\(di_{i,j,k}\),表示状态为棋子在\((i,j)\),空 ...
随机推荐
- 零基础2018如何系统地学习python?
首先告诉你的是,零基础学习开始系统学习Python肯定难,Python的专业程度本身就不简单,学习这事本来就是一件非常煎熬的事情,人都不愿意学习,可是没办法,为了生存掌握一个技能,你必须学,如果你认真 ...
- mysql cp复制和mysqldump备份测试
本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 备份策略 针对不同的场景下, 我们应该制定不同的备份策略对数据库进行 ...
- 为何要部署IPV6
·IPv4的局限性: 1.地址空间的局限性:IP地址空间的危机由来已久,并正是升级到IPv6的主要动力. 2.安全性:IPv4在网络层没有安全性可言,安全性一直被认为是由网络层以上的层负责. ...
- springboot入门_helloworld
开始学习springboot,在此做记录,有不正确之处,还望读者指正. springboot框架的设计目的是用来简化新Spring应用的初始环境搭建以及开发过程.主要体现有:1 xml配置文件,使用s ...
- C/C++语言简介之运算符
比较特别的是,比特右移(>>)运算符可以是算术(左端补最高有效位)或是逻辑(左端补 0)位移.例如,将 11100011 右移 3 比特,算术右移后成为 11111100,逻辑右移则为 0 ...
- Sphinx下载、安装、配置、Hello World、文档阅读
sphinx下载.安装.配置.Hello World.查看文档
- Java版2048
功能要求:2048的基本界面,能够实现2048的游戏功能. 总思路:两个类:Game和GameListener. Game负责界面的实现和paint方法的重写 GameListener负责实现键盘和鼠 ...
- Java--JDBC连接数据库(二)
本篇文章接着上篇文章,还剩下一个知识点是,可滚动的结果接集和可更新的结果集.一般默认情况之下,多结果集是不可以显式滚动,移动选择的.如果想要做到,需要指定一些参数,那么本篇就接着介绍如何操作可滚动的结 ...
- 企业内部DNS跨国配置案例
背景介绍:总公司与北京分公司均由总公司进行统一管理.总公司的主从DNS担任解析总公司服务器与北京分公司的服务器解析任务.总公司DNS委派其他两个公司管理自己域下的服务器解析任务.要求任何一个节点都能解 ...
- 约瑟夫环-循环队列算法(曾微软,google笔试题)
这也是我们聚会时常常做的游戏之一. 算法思路: 此处我使用循环链表模拟人围城一圈,每一个结点代表一个人.链表是一个有序链表,链表结点数据域是一个整型,代表人的序号.出局等同于链表删除元素,每次出局后重 ...