传送门

Luogu

解题思路

预支一点东西:

这题其实有着更为思维的图模型,还十分考验码力,不简单啊 这居然是联赛题

讲正解:

显然我们对于一种合法方案,空格子肯定是一直围绕着特定棋子反复横跳的。

所以说我们可以先预处理一下:对于任何一种合法的情况,求出空格在指定棋子的四个方向横跳的最小步数,这个可以通过多次 \(\text{BFS}\) 来求。

然后考虑处理询问。

不难想到任何一种走法都是先让空格来到指定棋子旁,然后进行上面提到的反复横跳,最后空格也一定会与指定棋子相邻。

所以说,我们就对于每一种指定棋子和空格的摆放情况创建一个节点,通过空格的横跳和指定棋子和空格的交换,也就是摆放情况的变化来连边。

每次询问时,我们先让空格来到指定棋子旁(这个需要枚举四个不同方向,当然要合法),

然后多源最短路,最后枚举一下终止状况,取最小步数的方案作为答案就好了。

说是这么说,其实码起来细节多得不得了啊。。。

细节注意事项

  • 爆搜题,你们懂得。。。

参考代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#include <queue>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while (!isdigit(c)) f |= c == '-', c = getchar();
while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
s = f ? -s : s;
} const int _ = 32;
const int __ = 10005;
const int dx[] = { -1, 0, 0, 1 };
const int dy[] = { 0, -1, 1, 0 }; int n, m, q, a[_][_];
int f[4][_][_][_][_], vis[_][_];
int Vis[__], dis[__];
struct node { int x, y; } ; int tot, head[__], nxt[__ << 3], ver[__ << 3], w[__ << 3];
inline void Add_edge(int u, int v, int d)
{ nxt[++tot] = head[u], head[u] = tot, ver[tot] = v, w[tot] = d; } inline int id(int x, int y, int t) { return (x - 1) * 120 + (y - 1) * 4 + t; } inline void calc(int sx, int sy) {
static queue < node > Q;
for (rg int k = 0; k < 4; ++k) {
memset(vis, -1, sizeof vis);
int x = sx + dx[k], y = sy + dy[k];
if (x < 1 || x > n || y < 1 || y > m) continue;
vis[x][y] = 1, f[k][sx][sy][sx][sy] = 0, Q.push((node) { sx, sy });
Add_edge(id(sx, sy, 3 - k), id(x, y, k), 1);
while (!Q.empty()) {
node u = Q.front(); Q.pop();
int x = u.x, y = u.y;
for (rg int t = 0; t < 4; ++t) {
int xx = x + dx[t], yy = y + dy[t];
if (xx < 1 || xx > n || yy < 1 || yy > m) continue;
if (vis[xx][yy] != -1 || !a[xx][yy] || (xx == sx && yy == sy)) continue;
f[k][sx][sy][xx][yy] = f[k][sx][sy][x][y] + 1;
vis[xx][yy] = 1, Q.push((node) { xx, yy });
}
}
for (rg int t = 0; t < 4; ++t) {
int xx = x + dx[t], yy = y + dy[t];
if (k + t == 3 || f[k][sx][sy][xx][yy] == 0x3f3f3f3f) continue;
Add_edge(id(sx, sy, 3 - k), id(xx, yy, t), f[k][sx][sy][xx][yy]);
}
}
} inline void init() {
memset(f, 0x3f, sizeof f);
for (rg int i = 1; i <= n; ++i)
for (rg int j = 1; j <= m; ++j)
if (a[i][j]) calc(i, j);
} inline void bfs(int ex, int ey, int sx, int sy) {
static queue < node > Q;
Q.push((node) { ex, ey });
vis[ex][ey] = 0;
while (!Q.empty()) {
node u = Q.front(); Q.pop();
int x = u.x, y = u.y;
for (rg int k = 0; k < 4; ++k) {
int xx = x + dx[k], yy = y + dy[k];
if (xx < 1 || xx > n || yy < 1 || yy > m) continue;
if (!a[xx][yy] || vis[xx][yy] != -1 || (xx == sx && yy == sy)) continue;
vis[xx][yy] = vis[x][y] + 1, Q.push((node) { xx, yy });
}
}
} inline void Dijkstra(int sx, int sy) {
static priority_queue < pair < int, int > > Q;
for (rg int k = 0; k < 4; ++k) {
int xx = sx + dx[k], yy = sy + dy[k];
if (xx < 1 || xx > n || yy < 1 || yy > m || !a[xx][yy]) continue;
int ID = id(xx, yy, k);
dis[ID] = vis[xx][yy] == -1 ? 0x3f3f3f3f : vis[xx][yy];
Q.push(make_pair(-dis[ID], ID));
}
while (!Q.empty()) {
int u = Q.top().second; Q.pop();
if (Vis[u]) continue; Vis[u] = 1;
for (rg int i = head[u]; i; i = nxt[i]) {
int v = ver[i];
if (dis[v] > dis[u] + w[i])
dis[v] = dis[u] + w[i], Q.push(make_pair(-dis[v], v));
}
}
} inline void solve() {
memset(Vis, 0, sizeof Vis);
memset(vis, -1, sizeof vis);
memset(dis, 0x3f, sizeof dis);
int ex, ey, sx, sy, tx, ty;
read(ex), read(ey), read(sx), read(sy), read(tx), read(ty);
if (sx == tx && sy == ty) { puts("0"); return ; }
bfs(ex, ey, sx, sy), Dijkstra(sx, sy);
int ans = 0x3f3f3f3f;
for (rg int i = 0; i < 4; ++i) {
int x = tx + dx[i], y = ty + dy[i];
if (x < 1 || x > n || y < 1 || y > m) continue;
ans = min(ans, dis[id(x, y, i)]);
}
if (ans == 0x3f3f3f3f) puts("-1"); else printf("%d\n", ans);
} int main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
read(n), read(m), read(q);
for (rg int i = 1; i <= n; ++i)
for (rg int j = 1; j <= m; ++j) read(a[i][j]);
init();
while (q--) solve();
return 0;
}

完结撒花 \(qwq\)

「NOIP2013」华容道的更多相关文章

  1. loj2613 「NOIP2013」华容道[最短路]

    感觉和以前做过的一个推箱子很像,都是可以用bfs解决的,而且都是手玩出结论. 因为起始棋子肯定是要和空格交换的,所以第一件事是先把空格移到棋子旁边.然后讨论怎么设计搜索状态.由于和推箱子实在太像了,所 ...

  2. 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA

    题目描述 AA国有nn座城市,编号从 11到nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最 ...

  3. LG1983 「NOIP2013」车站分级 拓扑排序

    问题描述 LG1983 题解 考虑建立有向边\((a,b)\),代表\(a\)比\(b\)低级. 于是枚举每一辆车次经过的车站\(x \in [l,r]\),如果不是车辆停靠的车站,则从\(x\)向每 ...

  4. 「NOIP2013」货车运输

    传送门 Luogu 解题思路 首先 \(\text{Kruskal}\) 一下,构造出一棵森林. 并查集还要用来判断连通性. 倍增 \(\text{LCA}\) 的时候顺便维护一下路径最小值即可. 细 ...

  5. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  6. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  7. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  8. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  9. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

随机推荐

  1. Hibernate学习(四)

    一对多测试案例 1.类图 2.创建表 drop table if exists t_student ; drop table if exists t_class ; create table t_cl ...

  2. 关于archive(feature)

    配置如下archive命令,可以记录登录到设备,具体配置了哪些命令: R3(config)#archiveR3(config-archive)#log configR3(config-archive- ...

  3. Root密码忘记修改方式!

    方法一:进入单用户: Linux系统开机进入引导画面,选择:CentOS Linux(3.10.0-693.e17.x86_64)7 (Core)   ,按字母 "E"键,进入Li ...

  4. python闯关之路一(语法基础)

      1,什么是编程?为什么要编程? 答:编程是个动词,编程就等于写代码,那么写代码是为了什么呢?也就是为什么要编程呢,肯定是为了让计算机帮我们搞事情,代码就是计算机能理解的语言. 2,编程语言进化史是 ...

  5. Codeforces1107E. Vasya and Binary String

    题目链接 本题也是区间dp,但是需要保存的信息很多,是1还是0,有多少个连续的,那我们可以预处理,将所有的连续缩合成1个字符,那么字符串就变成了一个01交替的串,我们任意的消除1个部分,一定能引起连锁 ...

  6. 设计模式课程 设计模式精讲 3-3 开闭原则 coding

    1 课程讲解 1.1 开闭原则定义 1.2 不重要内容 2 代码coding 2.1 基类 2.2 需求:打印出原价和折扣后的价格.(接口不应该随意变化,面向接口编程) 1 课程讲解 1.1 开闭原则 ...

  7. Aery的UE4 C++游戏开发之旅(4)加载资源&创建对象

    目录 资源的硬引用 硬指针 FObjectFinder<T> / FClassFinder<T> 资源的软引用 FSoftObjectPaths.FStringAssetRef ...

  8. 误删Django的model中的表解决办法

    误删Django的model中的表解决办法 1.model里面的表格实际的操作都在migrations文件夹中,里面记录了操作过程,当在database和model中删除表格时要注意初始化数据库时会报 ...

  9. selenium 参数设置-window.navigator.webdriver

    selenium 参数设置 selenium启动chrome基本上与真实环境类似,但有一些变量还是不一样,需要注意. 有些网站通过这些参数识别爬虫. window.navigator.webdrive ...

  10. PAT T1013 Image Segmentation

    krustral算法加并查集,按题给要求维护并查集~ #include<bits/stdc++.h> using namespace std; ; const int inf=1e9; i ...