IOI 2022 Day 1 Task2


Task2


囚徒挑战(prison)
⼀个监狱⾥关着 500 名囚徒。 有⼀天,监狱⻓给了他们⼀个重获⾃由的机会。 他把装钱的两个袋⼦ A 和 B 放在⼀个房间⾥。 每个袋⼦装有若⼲枚硬币,数量的范围在 1 到 N 之间(包含 1 和 N)。 两个袋⼦ ⾥硬币的数量不同。 监狱⻓给囚徒们提出了挑战,⽬标是指出硬币数量较少的那个袋⼦。

房间⾥除了袋⼦还有⼀块⽩板。 任意时刻⽩板上写着⼀个数,⼀开始写的是 0。

监狱⻓让囚徒⼀个接⼀个地进⼊房间。 每个进⼊房间的囚徒不知道他之前进⼊过房间的囚徒有多少⼈,也 不知道是哪些⼈。 每次⼀个囚徒进⼊房间时,他看⼀眼⽩板上⽬前写的这个数。 看完之后,他必须在袋⼦ A 和 B 之间做出选择。 接着,他检查⾃⼰选的那个袋⼦,知道了⾥⾯有多少枚硬币。 然后,这名囚徒必 须选择做以下两种⾏动之⼀:

1.将⽩板上的数改写成⼀个⾮负整数,并离开房间。 注意他可以改变成新的数,也可以保留当前的 数。 然后挑战继续进⾏(除⾮所有 500 名囚徒都已经进过房间)。

2.指出硬币数量较少的那个袋⼦。这会⽴即结束挑战。

对于已经进过房间的囚徒,监狱⻓不会让他再次进⼊房间。

如果某个囚徒正确地指出硬币较少的袋⼦,则囚徒们获得挑战的胜利。 如果指出的袋⼦不正确,或者所有 500 ⼈进过房间之后还没有⼈尝试指出硬币较少的袋⼦,则囚徒们失败。

挑战开始之前,囚徒们集合在监狱⼤厅商量应对挑战的共同策略,分以下三个步骤:
1.他们挑选⼀个⾮负整数 x,作为他们可能会写在⽩板上的最⼤的数。
2.他们决定对任意⼀个数 i (0 ≤ i ≤ x),如果某个囚徒进⼊房间后看到⽩板上写着数 i,那么他应该 去检查哪个袋⼦。
3.他们决定当某个囚徒得知选中的袋⼦⾥的硬币数量后要采取的⾏动。具体来说,对任意写在⽩板上 的数 i (0 ≤ i ≤ x) 和检查选中的袋⼦⾥的硬币数量 j (1 ≤ j ≤ N),他们要决定做出以下两种⾏动
之⼀:
⽩板上应该要写⼀个 0 到 x 之间(包含 0 和 x)的什么数;
指出哪个袋⼦是硬币较少的。

如果赢得挑战,监狱⻓会在囚徒们继续服刑 x 天后释放他们

你的任务是提出能够确保囚徒们赢得挑战的策略(不管袋⼦ A 和 B 中的硬币数量是多少)。 你的得分取 决于 x 的值(详⻅⼦任务⼀节)

实现细节

你要实现以下函数:

int[][] devise_strategy(int N)

N:每个袋⼦⾥硬币最多可能的数量。

该函数需要返回⼀个数组 s,它的每个元素是⻓度为 N + 1 的整数数组,表⽰你给出的策略。 x 的 值是数组 s 的⻓度减⼀。 对满⾜ 0 ≤ i ≤ x 的每个 i,数组 s[i] 表⽰囚徒在进⼊房间看到⽩板上写 着数 i 时要做的事情:
1. 如果囚徒应该检查袋⼦ A,则 s[i][0] 的值是 0;如果囚徒应该检查袋⼦ B,则该值是 1。
2. 令 j 为所选袋⼦中的硬币数量,囚徒应该进⾏以下⾏动:
如果 s[i][j] 的值是 −1,则囚徒应该指出袋⼦ A 是硬币较少的袋⼦。
如果 s[i][j] 的值是 −2,则囚徒应该指出袋⼦ B 是硬币较少的袋⼦。
如果 s[i][j] 的值是⾮负整数,则囚徒应该把这个数写到⽩板上。注意 s[i][j] ⾄多只能 是 x。

该函数恰好被调⽤⼀次。

例⼦

考虑以下调⽤:

devise_strategy(3)

令 v 表⽰囚徒进⼊房间时看到⽩板上写着的数。以下是⼀种正确的策略:
如果 v = 0(也包括开始时的数),则检查袋⼦ A。
如果它装了 1 个硬币,则指出袋⼦ A 是硬币较少的袋⼦。
如果它装了 3 个硬币,则指出袋⼦ B 是硬币较少的袋⼦。
如果它装了 2 个硬币,则在⽩板上写上 1(覆盖之前的 0)。

如果 v = 1,则检查袋⼦ B。
如果它装了 1 个硬币,则指出袋⼦ B 是硬币较少的袋⼦。
如果它装了 3 个硬币,则指出袋⼦ A 是硬币较少的袋⼦。
如果它装了 2 个硬币,则在⽩板上写上 0(覆盖之前的 1)。注意,这种情况其实不可能发 ⽣,因为此时两个袋⼦都装有 2 枚硬币,是不允许的。

要产⽣以上策略,函数应该返回 [[0, -1, 1, -2], [1, -2, 0, -1]]。 返回的数组⻓度是 2,此时 x 的值是 2 − 1 = 1。

约束条件

2 ≤ N ≤ 5000

⼦任务

  1. (5 分)N ≤ 500,x 的值不能超过 500
  2. (5 分)N ≤ 500,x 的值不能超过 70
  3. (90分)x 的值不能超过 60

对于任何测试⽤例,如果 devise_strategy 返回的数组是不合法的,则你在该⼦任务上的得分为 0。
⼦任务 3 有部分分。 令 m 为该⼦任务中所有测试⽤例返回数组对应的 x 的最⼤值,你的得分将根据下表 计算:
在这里插入图片描述

评测程序示例

评测程序⽰例按以下格式读取输⼊:
第 1 ⾏:N
第 2 + k ⾏ (0 ≤ k):A[k] B[k]
最后⼀⾏:−1

除第⼀⾏和最后⼀⾏外,每⾏表⽰⼀个场景。 将第 2 + k ⾏对应的场景称为场景 k。 场景 k 中,袋⼦ A 装有 A[k] 枚硬币,袋⼦ B 装有 B[k] 枚硬币。

评测程序⽰例⾸先调⽤ devise_strategy(N)。 x 的值是返回数组的⻓度减⼀。 如果评测程序⽰例检测 到 devise_strategy 返回的数组不符合实现细节中描述的约束,它会打印如下错误信息并退出:
s is an empty array:s 是空的数组(表⽰不合法的策略)。
s[i] contains incorrect length:存在⼀个下标 i (0 ≤ i ≤ x) 满⾜ s[i] 的⻓度不是 N + 1 。
First element of s[i] is non-binary:存在⼀个下标 i (0 ≤ i ≤ x) 满⾜ s[i][0] 既不是 0,也不是1。
s[i][j] contains incorrect value:存在下标 i, j (0 ≤ i ≤ x, 1 ≤ j ≤ N) 满⾜ s[i][j] 的值不在 −2 和 x 之间。

否则,评测程序⽰例产⽣两项输出内容
⾸先,评测程序⽰例以如下格式打印你的策略的输出:

第 1 + k ⾏ (0 ≤ k):场景 k 下你的策略的输出。 如果⽤该策略导致某个囚徒指出袋⼦ A 是硬币较 少的,则输出字符 A。 如果⽤该策略导致某个囚徒指出袋⼦ B 是硬币较少的,则输出字符 B。 如果 ⽤该策略后没有囚徒指出哪个袋⼦的硬币较少,则输出字符 X。

其次,评测程序⽰例以如下格式在当前⽬录下写⼀个⽂件 log.txt:
第 1 + k ⾏ (0 ≤ k):w[k][0] w[k][1] …

第 1 + k ⾏的序列对应于场景 k,描述了写在⽩板上的数。 具体来说,w[k][l] 是第 l + 1 个囚徒进⼊房间 后写的数。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值