1376: 向量场寻路算法
Description
题目背景
游戏开发中常提到“向量场寻路(Vector Field Pathfinding)”这个听起来高大上的算法。出题人打赌你们可能没有听过,而立志成为游戏客户端工程师的 ShadowDrunk 在研究了这个算法的底层原理后,坚定地认为:“这本质上不就是个基础的图论搜索遍历算法嘛!取这么个奇葩名字真是不好评价。”
今天,有一位同学拿着他用 Unity 制作的坦克大战 Demo 给 ShadowDrunk 看,并自豪地介绍他用 A* 算法实现了敌方坦克的寻路。虽然 A* 在游戏中应用广泛且有诸多变种,但在面对“地图上大量敌人同时追击玩家”的场景时,单体 A* 会带来巨大的性能开销。于是,ShadowDrunk 立刻想到了本题所描述的这个神奇算法。
题目描述
给定一个 $n \times m$ 的网格地图,其中 . 表示空地,# 表示障碍物。地图中存在一名玩家,坐标记录为 $(X_{player}, Y_{player})$,同时存在 $k$ 个敌方坦克,第 $i$ 个敌人的坐标为 $(X_i, Y_i)$($1 \le i \le k$)。
玩家和敌人都只能在空地上进行上下左右四个方向的移动,且无法穿过障碍物。
你需要设计一个算法,首先求出所有敌方坦克到达玩家位置的最短距离。
随后会有多次询问,你需要求出指定的敌人坦克到达玩家位置的最短路径。由于最短路径可能有多条,请输出字典序最小的一条最短路径。
路径表示与字典序规则:
- 路径由数字 1, 2, 3, 4 组成,分别代表:1-向上走,2-向下走,3-向左走,4-向右走。
- 字典序比较规则为逐位比较,单个元素的大小关系为 1 < 2 < 3 < 4。例如 123 < 143,12 < 123。
注意:本题的路径查询部分强制在线,具体的加密规则见输入格式。
Input
第一行包含两个整数 $n, m$($n \times m \le 10^6$),代表地图的大小。
第二行包含两个整数 $x, y$($1 \le x \le n, 1 \le y \le m$),代表玩家所在的坐标。
接下来 $n$ 行,每行包含 $m$ 个字符,用于表示地图网格(. 表示空地,# 表示障碍)。
接下来一行包含一个整数 $k$($1 \le k \le \text{空地的数量}$),代表敌方坦克的数量。
接下来 $k$ 行,每行包含两个整数 $x_i, y_i$,代表第 $i$ 个敌人的坐标。
接下来一行包含一个整数 $q$($1 \le q \le 10$),代表查询的次数。
接下来 $q$ 行,每行给出一个整数 $ind_{now}$,代表加密后的查询序号。
强制在线解密规则:
设上一次查询的真实序号为 $ind_{last}$(如果是第一次查询,则给出的 $ind_{now}$ 就是真实序号),本次查询的真实序号 $ind_{true}$ 计算公式为:
$$ind_{true} = (dis[ind_{last}] + ind_{now}) \pmod{2194188}$$其中,$dis[x]$ 代表第 $x$ 个敌人到达玩家的最短距离。你需要输出第 $ind_{true}$ 个敌人到达玩家字典序最小的最短路径。若上一个敌人无法到达则距离视为 $-1$。即此时$dis[ind_{last}] = -1$。
Output
第一行输出 $k$ 个整数(以空格分隔),代表 1 到 $k$ 号敌人到达玩家的最短距离。
如果该敌人无法到达玩家位置,最短距离输出 -1,且路径查询输出 -1。
接下来输出 $q$ 行,每行输出对应解密后的敌人到玩家的一条字典序最小的最短路径(操作序列以空格分隔)。无法到达则输出 -1。
Sample Input Copy
5 5
1 1
...#.
.....
##.##
.....
.....
3
3 3
2 2
5 5
2
1
2194187
Sample Output Copy
4 2 8
1 1 3 3
1 3 3 1 1 1 3 3
HINT
共有三个敌人。第一个敌人 (3, 3) 到玩家的距离为 4,第二个敌人 (2, 2) 到玩家的距离为 2,第三个敌人 (5, 5) 到玩家的距离为 8。
第一次查询:$ind_{now} = 1$,为第一次查询,故真实序号 $ind_{true} = 1$。第一个敌人到玩家字典序最小的路径为:上 上 左 左(1 1 3 3)。对应的 $dis[1] = 4$。
第二次查询:$ind_{now} = 2194187$。利用上一次的结果解密:$ind_{true} = (2194187 + dis[1]) \pmod{2194188} = (2194187 + 4) \pmod{2194188} = 3$。所以实际查询的是第三个敌人,其到玩家字典序最小的路径为:上 左 左 上 上 上 左 左(1 3 3 1 1 1 3 3)。