Codeforces #667D Vanya and Treasure

题目大意

有一个 $n \times m$ 的网格,网格上任意两个格点的距离定义为它们的曼哈顿距离。每个格点都有一个标号,第 $i$ 行第 $j$ 列的点标号为 $a_{ij}$($1\le a_{ij} \le p$) 。对于 $1$ 到 $p$ 之间的每个整数 $i$,至少存在一个格点标号为 $i$,并且只有一个点标号为 $p$ 。现欲从点 $(1,1)$ 依次经过标号为 $1,2,3\dots, p-1$ 的点,最后到达标号为 $p$ 的点,试求最短路的长度。

数据范围

$ 1 \le n, m \le 300 $
$ 1 \le p \le nm $

分析

How to approach the problem?

这道题可以看作是求分层图上两点间的最短路,所谓分层图指形如


的图。

分层图是一类特殊的 DAG,所以可用动态规划来求解单源最短路问题,复杂度为 $O(E) = O(n^2m^2)$,这个复杂度是无法接受的。

在介绍更优的算法之前,先谈一谈对网格图的两种认识。

对于曼哈顿距网格上的最短路问题,我们有两种方式来看待网格图。一是将网格图看作我们所关心的点的完全图 $K_c$ ($c$ 代表我们所关心的点的数目)或 $K_c$ 的某个子图,边权是两端点对应的格点的曼哈顿距离;二是将网格图看作「网格」,亦即一个 $n\times m$ 个点的无向图,每个点至多有 $4$ 个邻点,所有边长度都是 $1$ 。

上述「分层图上的 DP 算法」是用第一种观点来看待网格图。

算法二 $\DeclareMathOperator{\cnt}{cnt}$

用 $\cnt(x)$ 表示网格中编号为 $x$ 的点的数目,用 $V_x$ 表示编号为 $x$ 的点的集合;即有 $\cnt(x) = |V_x|$ 。

当 $\cnt(i)\times \cnt(i+1) < nm$ 时,遍历 $V_i$ 和 $V_{i+1}$ 之间的边,进行松弛操作。

当 $ \cnt(i)\times \cnt(i+1) \ge nm$ 时,从 $V_i$ 中的所有点开始在网格图上 BFS

在网格图上 BFS 一次的复杂度为 $O(nm)$ 。下面证明

调用 BFS 的次数至多为 $\sqrt{nm}$

首先,我们有 $\sum_{i=1}^{p} \cnt(i) = nm $ 且 $\cnt(i) > 0$ 。

若 $\cnt(i) \cnt(i+1) \ge nm $ 则由基本不等式有

$$ \frac{\cnt(i) + \cnt(i+1)}{2} \ge \sqrt{\cnt(i) \cnt(i+1) } \ge \sqrt{nm} $$

假设有 $k$ 组相邻的标号 $(i_1, i_1 +1 ) , \dots, (i_j, i_j+1) \dots, (i_k, i_k+1)$ 使得 $\cnt(i_j) \cnt(i_j + 1) \ge nm $ 则有

$$ nm = \sum_{i=1}^{p} \cnt(i) > \sum_{j = 1}^{k} \frac{\cnt(i_j) + \cnt(i_j + 1)}{2} \ge k\sqrt{nm} $$

从而有 $ k < \sqrt{nm} $ 。

松弛操作的总次数不超过 $2nm\sqrt{nm}$

证明:首先,我们有

$$\cnt(i) \cnt(i+1) < mn \implies \min(\cnt(i), \cnt(i+1)) < \sqrt{nm} $$

并且

$$ \cnt(i) \cnt(i+1) =\min(\cnt(i), \cnt(i+1)) \times \max(\cnt(i), \cnt(i+1)) $$

因此

\begin{aligned}
\sum_i \cnt(i) \cnt(i+1) &= \sum_i \min(\cnt(i), \cnt(i+1)) \times \max(\cnt(i), \cnt(i+1)) \\
&< \sqrt{nm} \sum_i \max(\cnt(i), \cnt(i+1)) \\
&< \sqrt{nm} 2 nm
\end{aligned}

其中求和指标 $i$ 取遍使得 $ \cnt(i) \cnt(i+1) < nm $ 的标号。

至此,我们证明了此算法的复杂度为 $O(nm\sqrt{nm})$ 。

这个算法还有一个变体,可以达到同样的渐近复杂度。

当 $\cnt(i)\le \sqrt{nm}$ 且 $\cnt(i+1) \le \sqrt{nm}$ 时,遍历 $V_i$ 和 $V_{i+1}$ 之间的边,进行松弛操作;否则在网格图上进行 BFS 。

不难证明,松弛操作的总次数不超过 $2nm\sqrt{nm}$,调用 BFS 的次数不超过 $2\sqrt{nm}$ 。

算法三

猜你喜欢

转载自www.cnblogs.com/Patt/p/9182496.html