vijos1846 [NOIP2013] 华容道【最短路】
传送门:https://vijos.org/p/1983
(其实noip的题各个oj都会有的,就不贴其它传送门了)
这道题真的是,怎么说,我都不知道怎么评价了= =。果然数据量小的题怎么暴力都可以过。。。当然我没说这一题要用最最暴力的bfs。
首先这一题的特点是给定一个图,之后有q(q <= 500)个询问,这很显然就是暗示我们要预处理。那么预处理什么呢?首先观察这一题,若你想让目标棋子移动到指定的位置,一定是分以下几步(注意移动棋子等价于移动空白格子):
1) 先把空白格子移动到目标棋子的四联通块上。
2) 这样,目标棋子就可以与空白格子交换位置以实现一次移动,交换完后,空白格子仍旧在目标棋子的四联通块上
3) 再让空白格子移动到目标棋子的四联通块的另外一个块上(很显然要“另外一个”,不然不就回去了嘛),然后goto step2
我们可以定义一种状态(x, y, k),表示目标棋子在(x, y)上,空白格子在其k方向上。所以此题的关键就是要预处理出一个go[i][j][k][p]数组,来表示目标棋子在(x, y)上,空白格子由目标棋子的k方向移动到p方向所需的最小步数,这个用bfs来处理就ok啦!剩下就是最短路了。
#include <cstdio>
#include <cstring>
#include <queue> const int dirx[4] = {0, 1, 0, -1}, diry[4] = {1, 0, -1, 0};
const int other[4] = {2, 3, 0, 1}; int n, m, q, mp[35][35], ex, ey, sx, sy, tx, ty;
int go[35][35][4][4], head_, tail, stp[35][35], d[35][35][4];
bool book[35][35][4];
struct st1 {
int x, y;
} que[920], h;
struct st2 {
int x, y, k, d;
bool operator<(const st2 & rhs) const {
return d > rhs.d;
}
}; inline void bfs1(int x, int y, int kk) {
memset(que, 0, sizeof que);
memset(stp, 0x3c, sizeof stp);
head_ = tail = 0;
que[tail++] = (st1){x + dirx[kk], y + diry[kk]};
stp[x + dirx[kk]][y + diry[kk]] = 0;
int xx, yy;
while (head_ != tail) {
h = que[head_++];
for (int k = 0; k < 4; ++k) {
xx = h.x + dirx[k];
yy = h.y + diry[k];
if (mp[xx][yy] && stp[xx][yy] == 0x3c3c3c3c) {
stp[xx][yy] = stp[h.x][h.y] + 1;
que[tail++] = (st1){xx, yy};
}
}
}
go[x][y][kk][0] = stp[x][y + 1];
go[x][y][kk][1] = stp[x + 1][y];
go[x][y][kk][2] = stp[x][y - 1];
go[x][y][kk][3] = stp[x - 1][y];
}
inline void bfs2(int x, int y) {
memset(que, 0, sizeof que);
memset(stp, 0x3c, sizeof stp);
head_ = tail = 0;
que[tail++] = (st1){x, y};
stp[x][y] = 0;
int xx, yy;
while (head_ != tail) {
h = que[head_++];
for (int k = 0; k < 4; ++k) {
xx = h.x + dirx[k];
yy = h.y + diry[k];
if (mp[xx][yy] && stp[xx][yy] == 0x3c3c3c3c) {
stp[xx][yy] = stp[h.x][h.y] + 1;
que[tail++] = (st1){xx, yy};
}
}
}
} int main(void) {
//freopen("in.txt", "r", stdin);
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf("%d", &mp[i][j]);
}
}
memset(go, -1, sizeof go);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (!mp[i][j]) {
continue;
}
mp[i][j] = 0;
for (int k = 0; k < 4; ++k) {
if (mp[i + dirx[k]][j + diry[k]]) {
bfs1(i, j, k);
}
}
mp[i][j] = 1;
}
} while (q--) {
scanf("%d%d%d%d%d%d", &ex, &ey, &sx, &sy, &tx, &ty);
if (sx == tx && sy == ty) {
puts("0");
continue;
}
mp[sx][sy] = 0;
bfs2(ex, ey);
mp[sx][sy] = 1;
memset(d, 0x3c, sizeof d);
memset(book, 0, sizeof book);
std::priority_queue<st2> hp;
if (stp[sx][sy + 1] < 0x3c3c3c3c) {
hp.push((st2){sx, sy, 0, stp[sx][sy + 1]});
}
if (stp[sx + 1][sy] < 0x3c3c3c3c) {
hp.push((st2){sx, sy, 1, stp[sx + 1][sy]});
}
if (stp[sx][sy - 1] < 0x3c3c3c3c) {
hp.push((st2){sx, sy, 2, stp[sx][sy - 1]});
}
if (stp[sx - 1][sy] < 0x3c3c3c3c) {
hp.push((st2){sx, sy, 3, stp[sx - 1][sy]});
}
d[sx][sy][0] = stp[sx][sy + 1];
d[sx][sy][1] = stp[sx + 1][sy];
d[sx][sy][2] = stp[sx][sy - 1];
d[sx][sy][3] = stp[sx - 1][sy]; st2 k;
int xx, yy;
while (!hp.empty()) {
k = hp.top();
hp.pop();
while (!hp.empty() && book[k.x][k.y][k.k]) {
k = hp.top();
hp.pop();
}
if (k.x == tx && k.y == ty) {
printf("%d\n", k.d);
goto spe;
}
book[k.x][k.y][k.k] = true;
xx = k.x + dirx[k.k];
yy = k.y + diry[k.k];
if (d[xx][yy][other[k.k]] > k.d + 1) {
d[xx][yy][other[k.k]] = k.d + 1;
hp.push((st2){xx, yy, other[k.k], k.d + 1});
}
for (int kk = 0; kk < 4; ++kk) {
if (d[k.x][k.y][kk] > k.d + go[k.x][k.y][k.k][kk]) {
d[k.x][k.y][kk] = k.d + go[k.x][k.y][k.k][kk];
hp.push((st2){k.x, k.y, kk, d[k.x][k.y][kk]});
}
}
}
puts("-1");
spe:;
}
return 0;
}
注意输入数据的(sx, sy)有可能与(tx, ty)相等。
vijos1846 [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剪枝,但这里的剪枝是 ...
- loj2613 「NOIP2013」华容道[最短路]
感觉和以前做过的一个推箱子很像,都是可以用bfs解决的,而且都是手玩出结论. 因为起始棋子肯定是要和空格交换的,所以第一件事是先把空格移到棋子旁边.然后讨论怎么设计搜索状态.由于和推箱子实在太像了,所 ...
- [NOIP2013]华容道
1.题面 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间.小 B 玩的华容道与经典 ...
- NOIP2013华容道 大爆搜
预处理出每个点周围四个点互相到达的最短路,再在整个图上跑SPFA,要记录路径 #include<cstdio> #include<cstring> #include<io ...
- luogu P1979 [NOIP2013] 华容道
传送门 这道题中,棋子的移动是要移动到空格上去,所以空格要在棋子旁边才能移动棋子;而棋子移动的方向由空格决定 所以我们可以记三维状态\(di_{i,j,k}\),表示状态为棋子在\((i,j)\),空 ...
随机推荐
- Excel小tips - 设置指定可选填充内容
数据——数据验证——设置——允许(A)——序列——来源 图1 数据验证界面 图2 选取序列数据字典 图3 效果展示 可以在同一个工作薄的同一个或者另一个工作表中设置指定内容(充当数据字典),然后点 ...
- [wxWidgets]_[0基础]_[不常见但有用的类wxCmdLineParser]
场景: 1. 有时候须要构造命令行字符串传递給函数调用,比方CreateProcess,假设參数是动态的,那么就得使用类似std::vector<string>加入单个參数,之后拼接为一个 ...
- enumerateObjectsUsingBlock 、for 、for(... in ...) 的差别 & 性能測试
for VS for(... in ...) for 的应用范围广基本能够NSArray.NSArray以及C语言的数组等,而for(... in ...)仅限于NSArray.NSArray等 fo ...
- IIS 配置 FTP 网站 H5 音频标签自定义样式修改以及添加播放控制事件
IIS 配置 FTP 网站 在 服务器管理器 的 Web服务器IIS 上安装 FTP 服务 在 IIS管理器 添加FTP网站 配置防火墙规则 说明:服务器环境是Windows Server 200 ...
- Android 封装实现各种样式对话框
先上图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/disso ...
- CodeSmith连Oracle
据说CodeSmith连Oracle特别麻烦,什么WIN7下不行,64位下不行.之前有个同事为了用上CodeSmith,还特地装了个XP虚拟机. 其实,还是那个连接串的问题. 操作系统64位,就要用6 ...
- (转载)synchronized代码块
原文:http://blog.csdn.net/luoweifu/article/details/46613015 作者:luoweifu 转载请标名出处 <编程思想之多线程与多进程(1)——以 ...
- hihocoder 第二十五周 spfa 最短路
其实hihocoder里的题目目前大都是模板题啊-.- 这周的是SPFA,暑假的时候有看过SPFA,不过一直用的都是Dijkstra,感觉spfa要更加简洁一点~~,今天找了一份之前一直都看不太懂所以 ...
- 推荐一款很好用的调试js的eclipse插件
ie调试的话用 Companion.JS 一个插件 很好用的 不用配置,直接安装eclipse调试的话 可以用jsdt 可能需要配置下 网上有很多说明http://wokaours.blog.163. ...
- 优化VMware提高虚拟机运行速度的技巧
vmware虚拟机如何设置不当的话会造成运行速度慢,并影响主机运行,甚至会出现死机. 以下是提高vmware虚拟机运行速度的几个技巧: 文章来自:http://blog.csdn.net/shanzh ...