你正站在打开的保险箱前,手里拿着一枚奖牌。但当你环顾四周时,胜利的喜悦瞬间化为绝望:你在房间里发现的一条领带上的信息显示,你的助手向科学委员会告发了你的计划!现在,两位委员会主席正躲在大楼里阻止你逃跑……
幸运的是,你从与其他选手的交易中剩下了一些真空吸尘器机器人。你想利用这些机器人定位两位主席,以便在逃跑时避开他们。你可以指示每个机器人侦察主席可能所在的 1000 个位置中的若干个。不幸的是,这些机器人的软件非常简单。每个机器人只能检测其侦察的位置中是否至少有一位主席。
更糟糕的是,每个机器人在返回结果给你之前,需要整整一个小时来侦察其位置。由于这会消耗机器人的电池,你只能派遣每个机器人一次。
由于你不想错过晚上的活动,你希望在最多 $H$ 小时后知道主席的位置。特别地,你可能被迫在不等待之前派遣的机器人返回的情况下,同时派遣多个机器人。你可以假设两位主席始终待在相同的位置。
请编写一个程序来规划这次侦察任务,并确定两位主席的位置。
交互
这是一个交互式任务。你必须实现函数 pair<int, int> scout(int R, int H),其中 $R$ 和 $H$ 如上所述。对于每个测试用例,该函数会被调用恰好一次,并应返回一对整数 $1 \le a, b \le 1000$(允许 $a = b$),即两位主席的位置。在 scout 内部,你可以使用评测机提供的以下其他函数:
void send(vector<int> P):派遣一个机器人去侦察位置 $P[0], \dots, P[k - 1]$(其中 $k$ 是数组 $P$ 的长度)。位置 $P[i]$ 必须是 1 到 1000 之间互不相同的整数。每个测试用例中,你最多可以调用此函数 $R$ 次。vector<int> wait():等待一小时。此函数返回一个数组,其中包含一小时前(通过在上次调用wait之后或程序开始后调用send)派遣的每个机器人的结果。如果第 $(i + 1)$ 个机器人在其侦察的位置中检测到至少一位主席,则索引 $i$ 处的条目为 1,否则为 0。每个测试用例中,你最多可以调用此函数 $H$ 次。
如果你的任何函数调用不满足上述约束,你的程序将立即被终止,并被判为该测试用例“不正确”(Not correct)。你不得向标准输出写入内容或从标准输入读取内容;否则,你可能会收到“安全违规”(Security violation!)的判决。但你可以自由地向标准错误流(stderr)写入内容。
你必须在源代码中包含文件 avoid.h。为了在本地测试你的程序,你可以将其与 sample_grader.cpp 链接,该文件可在 CMS 的任务附件中找到。有关示例评测机的描述,请参阅下文;有关如何将其与你的程序一起运行的说明,请参阅 sample_grader.cpp。附件中还包含一个示例实现 avoid_sample.cpp。
子任务
- 子任务 1(10 分):$R = 10, H = 1$,且两位主席位于相同位置。
- 子任务 2(5 分):$R = H = 20$。
- 子任务 3(10 分):$R = 30, H = 2$。
- 子任务 4(75 分):$R = 75, H = 1$。
部分得分:在子任务 4 中,你的实际得分取决于该子任务所有测试用例中派遣机器人数量的最大值 $r_{\max}$,具体遵循以下分段线性函数:
特别地,要在最后一个子任务中获得满分,每个测试用例调用 send 的次数不得超过 26 次。你也可以在任务附件的 score_table.txt 中找到列出所有个人得分的表格。
样例交互
考虑一个 $R = 75, H = 20$ 的测试用例,其中主席位于位置 13 和 37。首先,评测机调用你的函数 scout 为 scout(75, 20)。然后,你的程序与评测机之间的交互可能如下所示:
| 你的程序 | 返回值 | 说明 |
|---|---|---|
send({42, 13, 37}) |
— | 派遣一个机器人到位置 13, 37 和 42 |
send({47, 11}) |
— | 派遣一个机器人到位置 11 和 47 |
wait() |
{1, 0} |
等待一小时以获取机器人返回;只有第一个机器人检测到了主席 |
send({42}) |
— | 派遣一个机器人到位置 42 |
wait() |
{0} |
等待一小时;位置 42 没有主席 |
return {13, 37} |
— | 你确信主席位于位置 13 和 37 |
| 解决方案正确并被接受 |
返回对 {37, 13} 同样会被接受。注意,上述查询当然不足以确定主席的位置:例如,两位主席都在位置 37,或者一位主席在位置 13 而另一位在位置 100,也与 wait 的所有回答一致,因此评测机也可能拒绝该解决方案。
上述交互在公共测试用例上由 avoid_sample.cpp 重现。
评测机
示例评测机首先在标准输入中期望得到整数 $R$ 和 $H$,以及主席的位置 $a$ 和 $b$($1 \le a, b \le 1000$)。然后,评测机调用 scout(R, H) 并向标准输出写入你程序调用的所有评测机函数的协议。终止时,它会向标准输出写入以下消息之一:
Invalid input.:通过标准输入提供给评测机的输入格式不正确。Invalid send.:你调用send时使用了无效参数。Out of robots.:你调用send的次数超过了 $R$ 次。Out of time.:你调用wait的次数超过了 $H$ 次。Wrong answer.:scout返回的位置不是主席的位置。Correct: r robot(s) used, h hour(s) passed.:scout返回的位置是主席的位置,共调用了 $r$ 次send,调用了 $h$ 次wait。
相比之下,实际用于评测你程序的评测机只会输出 Not correct(针对上述任何错误)、Security violation! 或 Correct: r robot(s) used, h hour(s) passed.。此外,评测机是自适应的,即主席的位置可能取决于你的程序在当前以及之前运行中的行为。无论是示例评测机还是用于评测你程序的评测机,只要发生上述任何错误,都会自动终止你的程序。