#P6831. [IOI 2020] 嘉年华奖券

    ID: 7740 远端评测题 2000ms 1024MiB 尝试: 0 已通过: 0 显示难度省选/NOI− 上传者: 标签>贪心2020递归IOI交互题Special Judge

[IOI 2020] 嘉年华奖券

背景

本题为交互题。

请在程序开头声明 void allocate_tickets(std::vector<std::vector<int> > s); 和使用 vector 头文件,并且请在调用函数前加上 extern "C"。

请使用 C++17 / 20 提交。

题目描述

Ringo 正在参加在新加坡举办的一个嘉年华活动。他的口袋里装有一些奖券,这些奖券可以在嘉年华的游戏展位使用。假设共有 nn 种颜色的奖券,每张奖券涂上了其中的一种颜色并且印上了一个非负整数。不同奖券上的数字可能相同。依据嘉年华活动的规则要求,nn 保证是偶数。

Ringo 每种颜色的奖券有 mm 张,也就是说他共有 n⋅mn \cdot m 张奖券。其中,第 ii 种颜色对应的第 jj 张奖券上印的数字为 x[i][j]x[i][j](0≤i≤n−10 \le i \le n-1 且 0≤j≤m−10 \le j \le m-1)。

一次奖券游戏要进行 kk 轮,轮次的序号从 00 到 k−1k-1。每一轮按照下面的方式进行:

  • 首先,Ringo 从每种颜色的奖券中各选出一张奖券,形成一个 nn 张奖券的 集合。
  • 随后,游戏负责人记录下这个集合中奖券上的数字 a[0],a[1],…,a[n−1]a[0],a[1],\ldots,a[n-1]。不需要考虑这 nn 个整数的顺序。
  • 接下来,游戏负责人从一个幸运抽奖箱中抽取一张特殊卡片,上面印有整数 bb。
  • 对于上述集合中每一个奖券上的数字 a[i](0≤i≤n−1)a[i](0\le i \le n-1),游戏负责人会计算 a[i]a[i] 和 bb 的差的绝对值。让 SS 代表这 nn 个差的绝对值之和。
  • 所得到的数字 SS 就是 Ringo 本轮能够获得的奖励数额。
  • 一轮游戏结束后,本轮集合中的奖券全部被丢弃,不会在未来的轮次所使用。

当 kk 轮游戏结束后,Ringo 会丢弃口袋中的所有奖券。

通过仔细观察,Ringo 发现这个奖券游戏被操控了!实际上,幸运抽奖箱里面内置了一台打印机。在每一轮,游戏负责人首先找到一个能够最小化当前轮次游戏奖励的整数 bb,然后将该数字打印在他所抽取的特殊卡片上。

知道了这些信息之后,Ringo 想要设计每轮游戏中的奖券分配方案,使得 kk 轮游戏中获得的总体奖励数额之和最大。

实现细节

你需要实现下面这个函数:

long long find_maximum(int k,std::vector<std::vector<int>> x)
  • kk:游戏的轮数。
  • xx:一个 n×mn \times m 的数组,记录了奖券上的数字。每种颜色的奖券按照上面的数字非递减顺序排序。
  • 这个函数只会被调用一次。
  • 这个函数应该只调用一次函数 allocate_tickets(参见下面的内容),它描述了 kk 轮游戏中的奖券分配方案,每一轮对应一个奖券集合。奖券的分配方案应该使得所获奖励数额之和达到最大。
  • 这个函数需要返回能够获得的最大的奖励数额之和。

函数 allocate_tickets 按照如下的方式进行定义:

void allocate_tickets(std::vector<std::vector<int>> s)
  • ss:一个 n×mn \times m 的数组。如果第 ii 种颜色的第 jj 张奖券如果被分配到了第 rr 轮游戏,那么 s[i][j]s[i][j] 的值应该为 rr;如果未被使用,应该为 −1-1。
  • 对于 0≤i≤n−10 \le i \le n-1,在 s[i][0],s[i][1],…,s[i][m−1]s[i][0],s[i][1],\ldots,s[i][m-1] 中,每个值 0,1,…,k−10,1,\ldots,k-1 必须只出现一次,而其他元素应该为 −1-1。
  • 如果存在多种奖券分配方案能够达到最优的奖励数值,可以给出其中任何一种最优方案。

提示

样例说明

例 1

考虑下面的函数调用:

find_maximum(2, [[0, 2, 5],[1, 1, 3]])

这意味着:

  • 游戏共进行 k=2k=2 轮;
  • 第 00 种颜色奖券上的整数数字分别是 0,20,2 和 55;
  • 第 11 种颜色奖券上的整数数字分别是 1,11,1 和 33;

一种能够获得最优奖励数值的分配方案是:

  • 在第 00 轮,Ringo 选择第 00 种颜色的第 00 张奖券(印有整数 00)和第 11 种颜色的第 22 张奖券(印有整数 33)。本轮获得的最小奖励数额是 33。例如,游戏负责人可以选择 b=1b=1:∣1−0∣+∣1−3∣=1+2=3|1-0| + |1-3| = 1+2 = 3。
  • 在第 11 轮,Ringo 选择第 00 种颜色的第 22 张奖券(印有整数 55)和第 11 种颜色的第 11 张奖券(印有整数 11)。本轮能够获得的最小奖励是 44。例如,游戏负责人可以选择 b=3b=3:∣3−1∣+∣3−5∣=2+2=4|3-1|+|3-5|=2+2=4。
  • 因此,本次游戏两轮的奖励之和为 3+4=73+4=7。

为了给出这个分配方案,函数 find_maximum 应该按照如下方式调用 allocate_tickets:

allocate_tickets([[0, -1, 1], [-1, 1, 0]])

最终,函数 find_maximum 应该返回数字 77。

例 2

考虑下面的函数调用:

find_maximum(1, [[5, 9], [1, 4], [3, 6], [2, 7]])

这意味着:

  • 游戏只进行一轮;
  • 第 00 种颜色奖券上的数字分别是 55 和 99;
  • 第 11 种颜色奖券上的数字分别是 11 和 44;
  • 第 22 种颜色奖券上的数字分别是 33 和 66;
  • 第 33 种颜色奖券上的数字分别是 22 和 77;

一种能够获得最优奖励的分配方案是:

  • 在第 00 轮,Ringo 选择第 00 种颜色的第 11 张奖券(印有整数 99),第 11 种颜色的第 00 张奖券(印有整数 11),第 22 种颜色的第 00 张奖券(印有整数 33),第 33 种颜色的第 11 张奖券(印有整数 77)。本轮能够获得的最小奖励是 1212。例如,游戏负责人可以选择 b=3b=3:∣3−9∣+∣3−1∣+∣3−3∣+∣3−7∣=6+2+0+4=12|3-9| + |3-1| + |3-3| + |3-7| = 6 + 2 + 0 + 4 = 12。

为了给出这个分配方案,函数 find_maximum 应该按照如下方式调用 allocate_tickets:

allocate_tickets([[-1, 0], [0, -1], [0, -1], [-1, 0]])

最终,函数 find_maximum 应该返回数字 1212。

约束条件

  • 2≤n≤15002\le n\le 1500 且 nn 为偶数
  • 1≤k≤m≤15001\le k\le m\le 1500
  • 0≤x[i][j]≤1090 \le x[i][j] \le 10^9(对于所有的 0≤i≤n−10 \le i \le n-1 且 0≤j≤m−10 \le j \le m-1)
  • x[i][j−1]≤x[i][j]x[i][j-1] \le x[i][j](对于所有的 0≤i≤n−10 \le i \le n-1 且 0≤j≤m−10 \le j \le m-1)

子任务

  1. (11 分)m=1m=1
  2. (16 分)k=1k=1
  3. (14 分)0≤x[i][j]≤10 \le x[i][j] \le 1(对于所有的 0≤i≤n−10 \le i \le n-1 且 0≤j≤m−10 \le j \le m-1)
  4. (14 分)k=mk=m
  5. (12 分)n,m≤80n,m \le 80
  6. (23 分)n,m≤300n,m \le 300
  7. (10 分)没有额外约束条件

评测程序示例

评测程序示例按照下面的格式读入数据:

第 11 行:n m kn\ m\ k
第 2+i2+i 行(0≤i≤n−10 \le i \le n-1):x[i][0] x[i][1] … x[i][m−1]x[i][0]\ x[i][1]\ \ldots \ x[i][m-1]

评测程序示例按照下面的格式打印你的答案:

第 11 行:find_maximum 的返回值
第 2+i2+i 行(0≤i≤n−10 \le i \le n-1):s[i][0] s[i][1] … s[i][m−1]s[i][0]\ s[i][1]\ \ldots\ s[i][m-1]