noip 2013 华容道
/*双向bfs (得分和单项的一样多....)70*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 35
#define maxm 810010
using namespace std;
int n,m,q,g[maxn][maxn];
int X,Y,sx,sy,ex,ey,falg,vis[maxn][maxn];
int xx[]={,,,-};
int yy[]={,-,,};
int f[maxn][maxn][maxn][maxn],s[maxn][maxn][maxn][maxn];
struct node
{
int kx,ky,xi,yi;
node (int xxx, int yyy, int tt, int ss):kx(xxx), ky(yyy), xi(tt), yi(ss){};
};
queue<node>Q;
void Bfs()
{
if(sx==ex&&sy==ey)
{
printf("0\n");
falg=;return;
}
while(!Q.empty())Q.pop();
f[X][Y][sx][sy]=;
s[X][Y][sx][sy]=;
Q.push(node(X,Y,sx,sy));
for(int i=;i<;i++)
{
int nx=xx[i]+ex;
int ny=yy[i]+ey;
if(nx>&&nx<=n&&ny>&&ny<=m&&g[nx][ny]&&f[nx][ny][ex][ey]==)
{
f[nx][ny][ex][ey]=;
s[nx][ny][ex][ey]=;
Q.push(node(nx,ny,ex,ey));
}
}
while(!Q.empty())
{
node t=Q.front();Q.pop();
int x=t.kx,y=t.ky;
int xs=t.xi,ys=t.yi;
int T=f[x][y][xs][ys];
int k=s[x][y][xs][ys];
for(int i=;i<;i++)
{
int nx=x+xx[i];
int ny=y+yy[i];
xs=t.xi;ys=t.yi;
if(nx>&&nx<=n&&ny>&&ny<=m&&g[nx][ny])
{
if(nx==xs&&ny==ys)xs=x,ys=y;
if(f[nx][ny][xs][ys]==)
{
f[nx][ny][xs][ys]=T;
s[nx][ny][xs][ys]=k+;
Q.push(node(nx,ny,xs,ys));
}
else if(f[nx][ny][xs][ys]!=T)
{
printf("%d\n",s[nx][ny][xs][ys]+k+);
falg=;return;
}
} }
}
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&g[i][j]);
while(q--)
{
scanf("%d%d%d%d%d%d",&X,&Y,&sx,&sy,&ex,&ey);
falg=;memset(f,,sizeof(f));Bfs();
if(falg==)printf("-1\n");
}
return ;
}
/*
后来看了别人的思路 机智啊!
本来bfs不超时的 nm*nm 但是加上q次询问就T了
问题就在这 我们重复的bfs太多了 能不能一次预处理好呢
但是考虑到每次的起点终点还有空格位置是在变化的
所以我们要与处理一些与这些无关的 但是对答案还有贡献的
考虑到目标棋子的移动必须先让空格移动到4周
所以我们把每个空格和目标棋子的相邻的组合作为状态
也就是有n*m*4个状态 每个状态不是相邻的 互相转移需要一定的步数
这个步数就使我们要预处理的东西
然后把每个状态映射成一个图 将目标棋盘转化成同样的状态 然后跑最短路
具体的细节看代码把
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 35
#define maxm 810010
using namespace std;
int n,m,q,g[maxn][maxn],num,head[maxm],kx,ky,sx,sy,ex,ey;
int f[maxn][maxn],dis[maxm],vis[maxm],ans;
struct node{int u,v,t,pre;}e[maxm];
int xx[]={-,,,};//上下左右 和下面的对应
int yy[]={,,-,};
void Init()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&g[i][j]);
}
void Add(int from,int to,int dis)
{
num++;e[num].v=to;
e[num].t=dis;
e[num].pre=head[from];
head[from]=num;
}
void Bfs(int X,int Y,int xi,int yi,int k)
{
queue<int>qx,qy;
while(!qx.empty())qx.pop();
while(!qy.empty())qy.pop();
memset(f,,sizeof(f));
qx.push(xi);qy.push(yi);
f[xi][yi]=;//判重+步数记录
while(!qx.empty())
{
int x=qx.front();qx.pop();
int y=qy.front();qy.pop();
for(int i=;i<;i++)
{
int nx=x+xx[i];
int ny=y+yy[i];
if(nx==X&&ny==Y)continue;
if(nx>&&nx<=m&&ny>&&ny<=m&&g[nx][ny]&&f[nx][ny]==)
{
qx.push(nx);qy.push(ny);
f[nx][ny]=f[x][y]+;
}
}
}
if(k==)return;
for(int i=;i<;i++)
{
int nx=X+xx[i],ny=Y+yy[i];
if(f[nx][ny]==||(nx==xi&&ny==yi))continue;
Add(X**+Y*+k,X**+Y*+i,f[nx][ny]-);//一一映射
}
Add(X**+Y*+k,xi**+yi*+(k^),);//每组之间的状态连起来 这里的^ 就是左变变 上变下
}
void Ready()
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{ if(!g[i][j]) continue;
if(g[i-][j]) Bfs(i,j,i-,j,);
if(g[i+][j]) Bfs(i,j,i+,j,);
if(g[i][j-]) Bfs(i,j,i,j-,);
if(g[i][j+]) Bfs(i,j,i,j+,);
}
}
void SPFA()
{
queue<int>q;memset(dis,/,sizeof(dis));
for(int i=;i<;i++)
{
int nx=sx+xx[i];
int ny=sy+yy[i];
if(nx>&&nx<=n&&ny>&&ny<=m&&g[nx][ny]&&f[nx][ny])
{
int k=sx**+sy*+i;
q.push(k);vis[k]=;dis[k]=f[nx][ny]-;//转化成可表示的状态
}
}
while(!q.empty())
{
int k=q.front();q.pop();vis[k]=;
for(int i=head[k];i;i=e[i].pre)
if(dis[e[i].v]>dis[k]+e[i].t)
{
dis[e[i].v]=dis[k]+e[i].t;
if(vis[e[i].v]==)
{
vis[e[i].v]=;q.push(e[i].v);
}
}
}
}
int main()
{
Init();
Ready();
for(int i=;i<=q;i++)
{
scanf("%d%d%d%d%d%d",&kx,&ky,&sx,&sy,&ex,&ey);
if(sx==ex&&sy==ey)
{
printf("0\n");continue;
}
Bfs(sx,sy,kx,ky,);//把空格移到目标棋子附近
SPFA();ans=dis[];
for(int i=;i<;i++)
{
int k=ex**+ey*+i;
ans=min(ans,dis[k]);
}
if(ans==dis[])printf("-1\n");
else printf("%d\n",ans);
}
return ;
}
noip 2013 华容道的更多相关文章
- Luogu 1979 NOIP 2013 华容道(搜索,最短路径)
Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...
- 洛谷 P1979 [ NOIP 2013 ] 华容道 —— bfs + 最短路
题目:https://www.luogu.org/problemnew/show/P1979 真是一道好题... 首先考虑暴力做法,应该是设 f[i][j][x][y] 记录指定棋子和空格的位置,然后 ...
- NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】
NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...
- [Noip 2013 Day1-3] 货车运输 做法总结
[Noip 2013 Day1-3] 货车运输 做法总结 Online Judge:Luogu-1967 Label:启发式合并,离线,整体二分,按秩合并,倍增,最大生成树 打模拟离线赛时做到,顺便总 ...
- 【CodeVS 3290】【NOIP 2013】华容道
http://codevs.cn/problem/3290/ 据说2013年的noip非常难,但Purpleslz学长还是AK了.能A掉这道题真心orz. 设状态$(i,j,k)$表示目标棋子在$(i ...
- 【NOIP 2013 DAY2 T3】 华容道(spfa)
题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...
- 华容道 [NOIP 2013]
Describltion 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...
- 【noip】华容道
描述 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间. 小 B 玩的华容道与经典的 ...
- NOIP 2013
Prob.1 转圈游戏 找到循环节,然后快速幂.代码: #include<cstdio> #include<cstring> #include<iostream> ...
随机推荐
- BTREE与HASH的区别
对于 B-tree 和 hash 数据结构的理解能够有助于预测不同存储引擎下使用不同索引的查询性能的差异,尤其是那些允许你选择 B-tree 或者 hash 索引的内存存储引擎. B-Tree 索引的 ...
- OC-深浅复制
[OC学习-26]对象的浅拷贝和深拷贝——关键在于属性是否可被拷贝 对象的拷贝分为浅拷贝和深拷贝, 浅拷贝就是只拷贝对象,但是属性不拷贝,拷贝出来的对象和原来的对象共用属性,即指向同一个属性地址. 深 ...
- avi文件格式详解【转】
AVI是音频视频交错(Audio Video Interleaved)的英文缩写,它是Microsoft公司开发的一种符合RIFF文件规范的数字音频与视频文件格式,原先用于Microsoft Vide ...
- 总结iOS 8和Xcode 6的各种坑
模拟器的路径从之前的~/Library/Application Support/iPhone Simulator移动到了~/Library/Developer/CoreSimulator/Device ...
- vs2012 aps.net4.0/4.5尚未在web服务器上注册
安装了vs2015后,vs2012 启动后报错: aps.net4.0/4.5尚未在web服务器上注册 解决办法: 下载微软补丁: http://blogs.msdn.com/b/webdev/arc ...
- 【数学】CSU 1810 Reverse (2016湖南省第十二届大学生计算机程序设计竞赛)
题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1810 题目大意: 一个长度为N的十进制数,R(i,j)表示将第i位到第j位翻转过来后的 ...
- 导出C++ dll文件
方法1. 直接新建 Qt dll library, 使用工程自动创建的宏定义 方法2. (1)新建一个Empty的Win32项目(如ExampleDLL),选择Application type 为DL ...
- CodeForces 689A -Mike and Cellphone
题目链接:http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=412142 题目大意: 给定一个0-9数字键盘,随后输入一个操 ...
- Java中的数据类型及相互转换方法
本文主要讲解两个部分: 一.Java中的数据类型有哪些? 二.数字类型和字符串类型相互转换的方法? 一.Java中的数据类型有哪些: Java中的数据类型有:基本数据类型和引用数据类型: 基本数据类型 ...
- [Java] Map / HashMap - 源代码学习笔记
Map 1. 用于关联 key 和 value 的对象,其中 key 与 key 之间不能重复. 2. 是一个接口,用来代替 Java 早期版本中的 Dictionary 抽象类. 3. 提供三种不同 ...