Memory 游戏使用 50 张牌进行。每张牌的正面印有 A 到 Y(ASCII 码 65 到 89)中的一个字母,使得每个字母恰好出现在两张牌上。牌被随机洗牌并正面朝下放置在桌面上。
Jack 通过翻开两张牌来玩这个游戏,使字母可见。对于 25 个字母中的每一个,当 Jack 第一次看到两张正面朝上的牌上都有同一个字母时,他会从母亲那里得到一颗糖果。例如,当 Jack 第一次翻开两张都包含字母 M 的牌时,他会得到一颗糖果。无论两张牌上的字母是否相同,Jack 随后都会将这两张牌再次翻回正面朝下。这个过程会重复进行,直到 Jack 收到 25 颗糖果——每个字母对应一颗。
你需要实现一个过程 play 来进行游戏。你的实现应该调用由评测系统实现的 faceup(C) 过程。C 是一个 1 到 50 之间的数字,表示你希望翻开的特定牌。该牌当前不能处于正面朝上的状态。faceup(C) 返回印在牌 C 上的字符。
在每两次调用 faceup 后,评测系统会自动将这两张牌再次翻回正面朝下。
你的 play 过程只有在 Jack 收到所有 25 颗糖果后才能终止。即使在 Jack 拿到最后一颗糖果之后,也允许继续调用 faceup(C)。
样例
以下是你的 play 过程可能进行的一系列调用及其说明。
| 调用 | 返回值 | 说明 |
|---|---|---|
faceup(1) |
'B' | 牌 1 包含 B。 |
faceup(7) |
'X' | 牌 7 包含 X。字母不相同。 |
| 评测系统自动将牌 1 和 7 翻回正面朝下。 | ||
faceup(7) |
'X' | 牌 7 包含 X。 |
faceup(15) |
'O' | 牌 15 包含 O。字母不相同。 |
| 评测系统自动将牌 7 和 15 翻回正面朝下。 | ||
faceup(50) |
'X' | 牌 50 包含 X。 |
faceup(7) |
'X' | 牌 7 包含 X。Jack 得到了他的第一颗糖果。 |
| 评测系统自动将牌 50 和 7 翻回正面朝下。 | ||
faceup(7) |
'X' | 牌 7 包含 X。 |
faceup(50) |
'X' | 牌 50 包含 X。字母相同,但 Jack 没有得到糖果。 |
| 评测系统自动将牌 7 和 50 翻回正面朝下。 | ||
faceup(2) |
'B' | 牌 2 包含 B。 |
| ... | ... | (省略部分函数调用) |
| ... | ... | ... |
faceup(1) |
'B' | 牌 1 包含 B。 |
faceup(2) |
'B' | 牌 2 包含 B。Jack 得到了他的第 25 颗糖果。 |
子任务
子任务 1 [50 分]
实现任何符合游戏规则并在时间限制内完成游戏的策略。
例如,有一种简单的策略,总是进行恰好 $2*(49+48+...+2+1) = 2450$ 次 faceup(C) 调用。
子任务 2 [50 分]
实现一种策略,在最多 100 次 faceup(C) 调用内完成任何可能的对局。
实现细节
- 实现文件夹:
/home/ioi2010-contestant/memory/ - 参赛者需实现:
memory.c或memory.cpp或memory.pas - 参赛者接口:
memory.h或memory.pas - 评测系统接口:
grader.h或graderlib.pas - 样例评测程序:
grader.c或grader.cpp或grader.pas以及graderlib.pas - 样例评测程序输入:
grader.in.1。 注意:输入文件包含一行 50 个字符,表示牌上的字母,顺序从 1 到 50。 - 样例评测程序的预期输出:如果你的实现正确,输出文件将包含
OK n,其中n是调用faceup(C)的次数。 - 编译并运行(命令行):
runc grader.c或runc grader.cpp或runc grader.pas - 编译并运行(gedit 插件):
Control-R,在编辑任何实现文件时。 - 提交(命令行):
submit grader.c或submit grader.cpp或submit grader.pas - 提交(gedit 插件):
Control-J,在编辑任何实现文件或评测文件时。