在 Bytemore 市,犯罪率达到了历史新高。在各种违法行为中,抢劫案每天都在发生。每当犯罪发生时,总是由一名独自巡逻的警官在连接街道拐角(通常简称为拐角)的狭窄小巷中追捕劫匪。不幸的是,劫匪往往能逃脱追捕,因为他们比警察更熟悉这座城市。
Bytemore 市警察局(BCPD)正在组织一次峰会以减少犯罪。其中一项举措是在追捕劫匪时使用计算机辅助。为此,BCPD 制作了一幅精确的城市地图。现在他们需要计算机软件来寻找追捕策略。
一名警官追捕一名劫匪的追捕问题建模如下:
- 警官选择一个拐角进行巡逻。
- 劫匪随后选择一个拐角进行抢劫(他知道警官在哪里)。从这一刻起,始终假设警官和劫匪都知道彼此的位置。
- 警官的移动包括:移动 to 相邻的拐角(即通过小巷与当前拐角相连的拐角)或等待(即不移动)。
- 劫匪的移动包括:移动到相邻的拐角。注意,与警察不同,劫匪不能等待。保持奔跑是他们的本能。
警官和劫匪轮流进行移动(从警官开始),直到发生以下情况之一:
- (a) 局面重复(局面由两者的位置以及轮到谁移动决定)。这对应于劫匪能够无限期地避开警官,因此劫匪逃脱;
- (b) 在其中一方移动后,警官和劫匪在同一个拐角相遇。在这种情况下,警官抓住了劫匪。
任务
你需要编写一个程序,在给定城市地图的情况下,确定是否可能抓住劫匪,如果可能,则代表警官进行移动以抓住他。
你的程序必须假设劫匪会采取最优策略移动。
实现细节
你需要实现两个函数:
start(N, A),它接受以下参数:- $N$ — 拐角的数量(拐角编号为 $0$ 到 $N - 1$);
- $A$ — 一个描述小巷的二维数组:对于 $0 \le i, j \le N - 1$, $$A[i, j] = \begin{cases} \text{false} & \text{如果 } i \text{ 和 } j \text{ 没有被任何小巷连接} \\ \text{true} & \text{如果 } i \text{ 和 } j \text{ 被一条小巷连接} \end{cases}$$ 所有小巷都是双向的(即对于所有 $i$ 和 $j$ 的值,有 $A[i, j] = A[j, i]$),并且不会有小巷将一个拐角与自身相连(即对于所有 $i$ 的值,$A[i, i]$ 均为 $\text{false}$)。此外,你可以假设总是可以通过沿着小巷移动从任意拐角到达其他任意拐角。 如果可以在参数描述的地图上抓住劫匪,函数 `start` 应该返回警官选择开始巡逻的拐角编号。否则,它应该返回 $-1$。
nextMove(R),它接受劫匪当前所在的拐角编号 $R$ 作为参数,并且必须返回警官移动后所在的拐角编号。
在对 nextMove 进行任何调用之前,函数 start 将被精确调用一次。如果 start 返回 $-1$,则不会调用 nextMove。否则, nextMove 将被重复调用,直到追捕结束。更具体地说,一旦发生以下情况之一,程序将立即终止:
nextMove返回了无效的移动;- 局面重复;
- 劫匪被抓住。
样例
让我们来看看右图所示的例子。在这种情况下,任何拐角都是警官的良好起点。如果他从拐角 $0$ 开始,他可以在第一步中等待,劫匪就会撞上他。另一方面,如果他从任何其他拐角开始,他可以等待直到劫匪移动到拐角 $0$,然后移动到那里。
以下是样例交互过程:
| 函数调用 | 返回值 |
|---|---|
start(4, [[0, 1, 1, 1], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]) |
3 |
nextMove(1) |
3 |
nextMove(0) |
0 |
注意:在上述 start 的调用中,为了简便起见,用 $0$ 表示 false,用 $1$ 表示 true。
子任务
- 子任务 1(16 分):$2 \le N \le 500$。每对拐角之间将恰好由一条小巷路径连接。
- 子任务 2(14 分):$2 \le N \le 500$。拐角和小巷的网络将形成一个网格状结构。网格将至少有两行和两列,街道拐角的编号将遵循下图所示的模式。
- 子任务 3(30 分):$2 \le N \le 100$。
- 子任务 4(40 分):$2 \le N \le 500$。
你的解决方案应该满足两个要求:
- 正确判断警官是否能抓住劫匪;
- 如果可以,代表警官进行移动并成功抓住劫匪。
在子任务 1 和 2 中,你的解决方案必须同时满足这两个要求才能获得任何分数。
在子任务 3 和 4 中,仅实现第一个要求的解决方案将获得该子任务 30% 的分数。如果你的解决方案仅旨在获得部分分数,你可以通过输出任何无效移动(例如在 nextMove 中返回 $-1$)来终止程序。
请注意,必须满足标准要求(时间限制、内存限制、无运行时错误)才能获得任何分数。
数据范围
- 时间限制:1.5 s
- 内存限制:256 MB
评测方式
你电脑上的样例评测程序(grader)将从标准输入读取数据。
输入的第一行应包含整数 $N$ — 拐角的数量。
接下来的 $N$ 行应包含邻接矩阵 $A$。这些行中的每一行都应包含 $N$ 个数字,每个数字为 $0$ 或 $1$。该矩阵必须是对称的,且主对角线上的值必须全部为 $0$。
下一行应包含数字 $1$(如果警察可以抓住劫匪)或 $0$(否则)。
最后,如果警官可以抓住劫匪,则应接续 $N$ 行,描述劫匪的策略。这些行中的每一行都应包含 $N + 1$ 个介于 $0$ 到 $N - 1$ 之间的整数。第 $r$ 行第 $c$ 列(其中 $c < N$)的值对应于以下情况:轮到劫匪移动,警官在拐角 $r$,劫匪在拐角 $c$,该值表示劫匪必须移动到的拐角。主对角线上的值将被忽略,因为它们对应于劫匪和警官在同一个拐角的情况。第 $r$ 行的最后一个值定义了如果警官的起始拐角为 $r$ 时,劫匪的起始拐角。
以下是样例评测程序的一个输入示例,代表三个相互连接的拐角:
3 0 1 1 1 0 1 1 1 0 1 0 2 1 2 2 0 0 2 1 0 0 1
以下是与上述题目描述中的示例相匹配的输入:
4 0 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 2 0 0 0 2 3 0 0 0 3 1 0 0 0 1