#P16268. [NOISG 2019] Shuffle
[NOISG 2019] Shuffle
题目背景
Lim Li 非常喜欢动画,最近她从 Amazon 购买了一整季《干物妹!小埋》。这一季共有 集,对应 张 CD。CD 的标签编号为 ,剧集编号也为 。
然而,由于生产故障,CD 标签编号与其中实际存放的剧集编号并不对应。Amazon 告诉她:所有剧集都在这套 CD 中,没有缺失,只是顺序被打乱了。
为了避免剧透,Lim Li 不愿意自己播放 CD 来确认每张 CD 对应哪一集。于是她决定请朋友 Rar the Cat 帮忙。
一次询问的过程如下:
- Lim Li 将 张 CD 分成 个盒子,每个盒子中恰好有 张 CD,满足 。
- 这些盒子会寄给 Rar。在运输过程中,每个盒子内部 CD 的顺序可能被打乱;除第 3 个子任务外,盒子之间的顺序也可能被打乱。
- Rar 收到盒子后,会播放 CD,并记录每个盒子中 CD 对应的剧集编号。
- Rar 将每个盒子的剧集编号分别写在 张纸上寄回给 Lim Li。每张纸上有 个整数,表示某个盒子中 CD 对应的剧集编号。
- 所有 CD 会被寄回给 Lim Li。
这个过程最多可以进行 次。请帮助 Lim Li 确定每个 CD 标签对应的实际剧集编号,并尽量减少询问次数。
题目类型
本题为 函数式交互 / Grader 题。
选手程序不要读入标准输入,也不要向标准输出输出内容。你只需要包含头文件 shuffle.h,并实现指定函数 solve。
评测时,系统会自动提供评测主程序 grader.cpp,并将其与你提交的程序一起编译运行。
需要实现的函数
你需要实现:
#include "shuffle.h"
std::vector<int> solve(int N, int B, int K, int Q, int ST);
该函数会被调用恰好一次。
参数含义如下:
- :CD 数量,同时也是剧集数量;
- :每次分组的盒子数量;
- :每个盒子中的 CD 数量;
- :最多允许调用
shuffle的次数; - :当前测试点所属的子任务编号。
函数应返回一个长度为 的数组 ans,其中 ans[i-1] 表示标签编号为 的 CD 中实际存放的剧集编号。
可以调用的函数
你可以调用评测器提供的函数:
std::vector<std::vector<int>> shuffle(std::vector<std::vector<int>> boxes);
参数 boxes 表示 Lim Li 当前的分盒方案。它必须满足:
boxes恰好包含 个数组;- 每个数组恰好包含 个整数;
- 所有整数合起来必须恰好是 的一个排列。
也就是说,boxes 的每一行表示一个盒子中放入的 CD 标签编号。
函数 shuffle 会返回一个 的二维数组,表示 Rar 收到盒子后记录的剧集编号。返回结果中:
- 每一行对应某一个盒子中的 个剧集编号;
- 每行内部顺序可能被打乱;
- 除第 个子任务外,返回结果中各行的顺序也可能被打乱。
注意:传给 shuffle 的 boxes 本身不会被修改。
如果调用 shuffle 的次数超过 ,或者传入参数不合法,程序会被判为错误。
样例交互说明
假设:
并且真实对应关系为:
即标签 对应剧集 ,标签 对应剧集 ,依此类推。
此时评测器会调用:
solve(6, 3, 2, 100, 2)
一次可能的交互如下:
shuffle([[1, 2], [3, 4], [5, 6]]) = [[6, 2], [5, 4], [3, 1]]
这表示 Lim Li 分出的三个盒子分别装有标签 、、。运输后盒子顺序和盒内顺序可能改变,Rar 记录到的三个盒子中的剧集编号为 、、。
之后可能继续调用:
shuffle([[2, 6], [3, 1], [5, 4]]) = [[6, 1], [2, 5], [4, 3]]
shuffle([[6, 5], [4, 2], [3, 1]]) = [[5, 1], [3, 4], [2, 6]]
若你的程序最终确定真实对应关系为:
[3, 1, 4, 5, 2, 6]
则应从 solve 中返回这个数组。
约束条件
所有测试点满足:
单个测试点的时间限制为 秒。
子任务
| 子任务 | 分值 | 附加限制 |
|---|---|---|
| 1 | 2 | |
| 2 | 3 | |
| 3 | 12 | ,盒子之间的顺序不会被打乱 |
| 4 | 16 | |
| 5 | 15 | |
| 6 | 52 | ,详见下方计分方式 |
第 6 个子任务的计分方式
第 6 个子任务为特殊计分子任务。设你的程序在任意一个第 6 子任务测试点中使用的最大询问次数为 。
- 若 ,得 分;
- 若 ,得 分;
- 若 ,得 分;
- 若 ,得
分;
- 若 ,得 分。
本地测试输入格式
下发的本地评测器使用如下输入格式:
第一行包含五个整数:
第二行包含 个整数:
其中 表示标签编号为 的 CD 中实际存放的剧集编号。
正式评测时,选手程序不需要也不应该自行读取这些输入。
提交说明
选手提交文件中应包含:
#include "shuffle.h"
并实现:
std::vector<int> solve(int N, int B, int K, int Q, int ST) {
// 在这里实现你的算法
}
不要在提交文件中编写 main 函数。评测系统会自动提供 main 函数和 shuffle 函数。
下发文件与本地测试说明
本题下发文件中包含:
shuffle.h // 需要包含的头文件
shuffle.cpp // 选手代码模板
compile_cpp.sh // 本地编译脚本
grader.cpp // 本地评测器,实际文件名为 grader.cpp
run_cpp.sh // 本地运行脚本
sample.1.in // 样例输入
本地测试时,可以将自己的代码写入或替换 shuffle.cpp,然后在 Linux/macOS 环境下运行:
chmod +x compile_cpp.sh run_cpp.sh
./compile_cpp.sh
./run_cpp.sh < sample.1.in
如果程序正确,评测器会输出类似:
Correct. Used 4 out of 100 queries.
正式提交时,只需要提交实现了 solve 的源代码;不需要提交 grader.cpp、compile_cpp.sh 或 run_cpp.sh。
@下发文件