QOJ.ac

QOJ

حد الوقت: 5 s حد الذاكرة: 8 MB مجموع النقاط: 100 تفاعلية

#271. 厨师

الإحصائيات

Byteasar 是一名餐厅厨师,他有 $n$ 个订单需要完成。每个订单都写在一张纸条上,所有纸条都串在一根签子上。Byteasar 的目标是尽可能快地完成所有订单。由于订单很多,为了提高效率,他只会从签子的顶部取订单。不过,他可以同时处理几道菜。具体来说,如果签子上还剩下 $k$ 张纸条,他可以:

  • 取走最上面的一张纸条,并在 $jedno(k)$ 的时间内完成该订单。
  • 如果 $k > 1$,他可以从顶部取走两张纸条,并在 $dwa(k)$ 的时间内完成这两份订单。
  • 如果 $k > 1$,他可以从顶部取走 $\lfloor k/2 \rfloor$ 份订单,并在 $polowa(k)$ 的时间内完成它们。

这些操作会消耗 Byteasar 的体力,他初始的体力值为 $e$。具体而言,第三种操作非常费力,会使 Byteasar 的体力减少 1;第二种操作不消耗体力;而处理单个订单非常轻松,第一种操作会使 Byteasar 的体力增加 1。Byteasar 的体力值永远不能低于 0,除此之外,他会尽一切努力使完成所有订单的总时间最小化,即只要最终体力值非负,其具体数值并不重要。

请编写一个程序,确定完成所有订单所需的最短时间。你的程序需要与一个库进行交互,该库提供有关 Byteasar 及其厨房状态的所有必要信息。请注意本题的内存限制。

交互

要使用该库,请在程序开头包含以下内容:

  • C/C++: #include "ckuclib.h"
  • Pascal: uses pkuclib;

该库提供以下函数和过程:

  • dajn, daje 第一个函数返回一个整数 $n$,表示需要完成的订单数量;第二个函数返回一个整数 $e$,表示 Byteasar 的初始体力。

    • C/C++: int dajn(); int daje();
    • Pascal: function dajn: LongInt; function daje: LongInt;
  • jedno(k), dwa(k), polowa(k) 这些函数分别返回当签子上有 $k$ 张纸条时,执行处理一份、两份和一半(准确地说是 $\lfloor k/2 \rfloor$ 份)待处理订单所需的时间。对于 $k = 1$,dwa(k)polowa(k) 返回的值应被忽略。报告的时间是一个范围在 $1$ 到 $10^7$ 之间的整数。

    • C/C++: int jedno(int k); int dwa(int k); int polowa(int k);
    • Pascal: function jedno(k: LongInt): LongInt; function dwa(k: LongInt): LongInt; function polowa(k: LongInt): LongInt;
  • odpowiedz(wynik) 向库报告 $wynik$ 是完成所有订单所需的最短时间。调用此函数将终止你的程序执行。

    • C/C++: void odpowiedz(int wynik);
    • Pascal: procedure odpowiedz(wynik: LongInt);

你的程序不能读取任何数据(既不能从标准输入,也不能从任何文件)。此外,它不能向文件或标准输出写入任何内容。它可以写入标准诊断输出 (stderr) —— 但请记住,这会消耗宝贵的时间。库可以多次查询相同的值。

子任务

测试集由以下子任务组成。在每个子任务中,可能包含多个测试组。

子任务 数据范围 分值
1 $n, e \le 1000$ 12
2 $n, e \le 50\,000$ 8
3 $n, e \le 1\,000\,000$ 80

样例

样例执行过程

C/C++ Pascal Wynik
n = dajn(); n := dajn; 3
e = daje(); e := daje; 1
p[3] = polowa(3); p[3] := polowa(3); 1
p[2] = polowa(2); p[2] := polowa(2); 4
j[2] = jedno(2); j[2] := jedno(2); 2
j[1] = jedno(1); j[1] := jedno(1); 5
d[2] = dwa(2); d[2] := dwa(2); 6
odpowiedz(7); odpowiedz(7);

上述执行过程在形式上是正确的,但报告的结果可能不正确。从答案中可以推断出,执行 polowa 后接 dwa(成本为 $p[3] + d[2] = 7$)比执行一次 polowa 后接两次 jedno(成本为 $p[3] + j[2] + j[1] = 8$)更好。此外,当有三份待处理订单时,执行 jedno 是毫无意义的,因为 $p[3] = 1$ 而 $j[3] \ge 1$。由于 $e = 1$,无法执行两次 polowa。但如果不了解 dwa(3) 的成本,我们就无法判断执行 dwa 后接 jedno 是否比 7 更省时。

实现细节

dlazaw 文件夹中,有一个示例库可用于测试程序的正确性。该库从标准输入读取信息,格式如下:

  • 第一行包含两个整数 $n$ 和 $e$;
  • 第二行包含 $n$ 个范围在 $[1, 10^7]$ 之间的整数 —— 分别对应 $k = 1, \dots, n$ 时函数 jedno 的值;
  • 第三行和第四行分别包含函数 dwapolowa 的值(格式相同);即使 $k=1$ 时的值会被忽略,也必须提供。

该库的输入样例在文件 kuc0.in 中提供。一旦执行了 odpowiedz 过程,库就会将报告的答案写入标准输出。

同一目录下包含使用该库的示例程序 kuc.ckuc.cppkuc.pas。这些程序是不正确的;特别是,它们总是重复执行 polowa 操作,直到只剩下一张纸条,然后执行 jedno 操作。

要将你的程序与库一起编译,请执行以下命令:

  • C: gcc -O2 -static ckuclib.c kuc.c -lm -std=gnu99
  • C++: g++ -O2 -static ckuclib.c kuc.cpp -lm -std=c++11
  • Pascal: ppc386 -O2 -XS -Xt kuc.pas

你的程序文件和库文件应位于同一文件夹中。

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.