QOJ.ac

QOJ

Time Limit: 10 s Memory Limit: 32 MB Total points: 100 Interactive

#13800. 矩形游戏

Statistics

我们考虑一个双人游戏。玩家们获得一个 $x \times y$ 的矩形(其中 $x$ 和 $y$ 是正整数)。 玩家轮流进行操作。一次操作包括通过单次垂直或水平切割将一个矩形分成两个矩形。得到的矩形必须具有正整数尺寸。

一个 $4 \times 3$ 矩形的所有可能切割方式。

每次切割后,较小的矩形(即面积较小的那个)会被丢弃,另一个矩形会被传给另一个玩家。如果矩形被等分成两半,则丢弃其中一半。收到 $1 \times 1$ 矩形因而无法进行操作的玩家输掉游戏。

你的任务是编写一个程序来玩这个矩形游戏并获胜。程序必须使用一个特殊的库来玩游戏。该库为你提供了 dimension_x()dimension_y() 函数,它们返回矩形的尺寸。矩形的初始尺寸是介于 $1$ 到 $100\,000\,000$ 之间的整数。至少有一个维度大于 $1$。此外,在 50% 的测试用例中,尺寸不超过 $25$。

还有一个过程 cut(dir, position),由你的程序调用以进行操作。参数 dirposition 分别描述切割的方向和位置。参数 dir 必须是以下两个值之一:verticalhorizontal。如果 dir = vertical,则切割是垂直的,参数 position 指定切割的 $x$ 坐标(见上图),你必须确保 $1 \le \text{position} \le \text{dimension\_x()} - 1$。如果 dir = horizontal,则切割是水平的,参数 position 指定切割的 $y$ 坐标,你必须确保 $1 \le \text{position} \le \text{dimension\_y()} - 1$。

当你的程序启动时,它将作为其中一名玩家参与一局游戏。你的程序先手——它必须对初始矩形进行切割。当你的程序调用 cut 过程时,你的操作会被记录,控制权将传递给程序的对手。在对手操作后,控制权返回给你的程序。dimension_x()dimension_y() 返回的值将反映你和对手操作后的结果。一旦你的程序获胜、失败或进行了非法操作(即使用无效参数调用 cut 过程),它将被终止。终止你的程序是一个自动过程,因此只要有可能,你的程序就应该继续进行操作。你可以假设对于测试数据,你的程序总是存在必胜策略。

你的程序不得读写任何文件,不得使用标准输入/输出,且不得尝试修改程序之外的任何内存。违反这些规则中的任何一条都可能导致取消资格。

实验

为了让你对该库进行实验,我们提供了示例对手库:它们的源文件在 preclib.pascreclib.ccreclib.h 中。该库可以从 http://contest/ 下载。它们实现了一种非常简单的策略。当你运行程序时,它将与这些简单的玩家进行对战。你可以随意修改它们,并针对更好的对手测试你的程序。然而,在评测期间,你的程序将与不同的对手进行对战。

当你使用 TEST 接口提交程序时,它将与未修改的示例对手库一起编译。提交的输入文件将提供给程序的标准输入。输入文件应包含两行,每行包含一个整数。第一行应包含矩形的初始宽度,第二行应包含矩形的初始高度。这些尺寸由示例对手库读取。

如果你修改了 preclib.pas 库的实现部分,请使用以下命令重新编译它:ppc386 -O2 preclib.pas。该命令生成 preclib.opreclib.ppu 文件。编译你的程序需要这些文件,并且它们应该放在你的程序所在的目录中。请不要修改 preclib.pas 库的接口部分。

如果你修改了 creclib.c 库,请记住将其(连同 creclib.h)放在你的程序所在的目录中——编译程序需要它们。请不要修改 creclib.h 文件。

还为你提供了两个简单的程序,说明上述库的使用方法:crec.cprec.pas。(请记住,这些程序不是正确的解决方案。)你可以使用以下命令编译它们:

gcc -O2 -static crec.c creclib.c -lm
g++ -O2 -static crec.c creclib.c -lm
ppc386 -O2 -XS prec.pas

你获得了一个提供以下功能的库:

  • FreePascal 库 (preclib.ppu, preclib.o)
type direction = (vertical, horizontal);
function dimension_x(): longint;
function dimension_y(): longint;
procedure cut(dir: direction; position: longint);

在你的源文件 rec.pas 中包含以下语句:

uses preclib;

要编译你的程序,请将文件 preclib.opreclib.ppu 复制到源文件所在的目录,并运行以下命令:

ppc386 -O2 -XS rec.pas

文件 prec.pas 给出了如何使用 preclib 库的示例。

  • GNU C/C++ 库 (creclib.h, creclib.c)
typedef enum __direction {vertical, horizontal} direction;
int dimension_x();
int dimension_y();
void cut(direction dir, int position);

在你的源文件(rec.crec.cpp)中包含以下语句:

#include "creclib.h"

要编译你的程序,请将文件 creclib.ccreclib.h 复制到源文件所在的目录,并运行以下命令:

gcc -O2 -static rec.c creclib.c -lm

或:

g++ -O2 -static rec.cpp creclib.c -lm

文件 crec.c 给出了如何在 C 中使用该库的示例。

样例交互

以下是你的程序与评测库之间的样例交互。它展示了一局样例游戏是如何进行的。游戏从一个 $4 \times 3$ 的棋盘开始。对于这个状态,存在必胜策略。

你的程序调用 发生的事情
dimension_x() 返回 4
dimension_y() 返回 3
cut(vertical, 1) 记录你的切割,并将一个 $3 \times 3$ 的棋盘传递给你的对手,对手将其切割为 $3 \times 2$ 的棋盘;在此之后,控制权返回给你的程序
dimension_x() 返回 3
dimension_y() 返回 2
cut(horizontal, 1) 记录你的切割,并将一个 $3 \times 1$ 的棋盘传递给你的对手,对手将其切割为 $2 \times 1$ 的棋盘;在此之后,控制权返回给你的程序
dimension_x() 返回 2
dimension_y() 返回 1
cut(vertical, 1) 你的切割产生了一个 $1 \times 1$ 的棋盘,因此你获胜;你的程序自动终止

Discussions

About Discussions

The discussion section is only for posting: General Discussions (problem-solving strategies, alternative approaches), and Off-topic conversations.

This is NOT for reporting issues! If you want to report bugs or errors, please use the Issues section below.

Open Discussions 0
No discussions in this category.

Issues

About Issues

If you find any issues with the problem (statement, scoring, time/memory limits, test cases, etc.), you may submit an issue here. A problem moderator will review your issue.

Guidelines:

  1. This is not a place to publish discussions, editorials, or requests to debug your code. Issues are only visible to you and problem moderators.
  2. Do not submit duplicated issues.
  3. Issues must be filed in English or Chinese only.
Active Issues 0
No issues in this category.
Closed/Resolved Issues 0
No issues in this category.