Time Limit: 2 sec / Memory Limit: 1024 MB
ストーリー
AtCoder社は最短路アルゴリズムを活用した道案内アプリを開発している。 サービスの対象エリアは30×30個の頂点をグリッド状に繋いだ道路網で表される。 ユーザーが現在位置の頂点と目的地の頂点を指定すると、アプリはその間の最短経路を出力する予定だ。 困ったことに、アプリのリリース予定日が迫っているにもかかわらず、最短経路の計算に必要不可欠な各辺の長さの計測が全く出来ていない。 そこで、事前に辺の長さを計測することを諦め、最短でないパスの出力も許すことにした。 ユーザーが目的地に到着するまでに実際にかかった時間の情報をもとに、出力した各辺の長さを推測することで、徐々に性能の改善が可能であるはずだ。
問題文
辺の長さが未知の30×30頂点の無向グリッドグラフがある。 一番左上の頂点を (0,0) とし、そこから下方向に i 回、右方向に j 回移動した先の頂点を (i, j) とする。 以下のクエリを1000個処理せよ。
k番目のクエリでは、まずはじめに、標準入力から頂点 s_k=(si_k,sj_k) と t_k=(ti_k,tj_k) が以下の形式で与えられる。
si_k sj_k ti_k tj_k
入力を読み込んだら、あなたのプログラムは s_k から t_k へのパス P_k を1つ求める。
(i, j) から (i-1,j), (i+1,j), (i,j-1), (i,j+1) の頂点への移動をそれぞれ U
, D
, L
, R
として、P_k を文字列で表し、標準出力に一行で出力せよ。
出力のあとは標準出力を flush しなければならない。そうしない場合、TLE
となる可能性がある。
パスが出力されると、ジャッジプログラムはパスの長さ b_k を計算し、0.9 以上 1.1 以下の一様乱数 e_k を生成して、整数値 \mathrm{round}(b_k\times e_k) を標準入力に与える。 それを読み込むことでk番目のクエリが終了し、k+1番目のクエリへ進む。
例
Input | Output |
---|---|
3 19 16 17 |
|
DDDDDDDDDDDDDLL |
|
99561 |
|
26 18 13 18 |
|
UUUUUUUUUUUUU |
|
72947 |
得点
k 番目 (1\leq k\leq 1000) のクエリに対する最短路長を a_k、出力されたパスの長さを b_k とすると、以下の得点が得られる。
\mathrm{round}(2312311\times \sum_{k=1}^{1000}0.998^{1000-k} \frac{a_k}{b_k})
各テストケースの得点の合計が提出の得点となる。
不正なパス(同じ頂点を複数回通る、30×30の外へはみ出す、sからtへのパスでない)が出力された場合、WA
と判定される。
コンテスト終了後に一番最後の提出に対してシステムテストが行われ、最終順位が決定される。
- 暫定テストは100個のテストケースを用いる。1つ以上のテストケースで
AC
以外の判定がされた場合、提出の得点は0点となる。 - システムテストは3000個のテストケースを用いる。
AC
以外の判定がされた場合、そのテストケースのみ0点となる。コンテスト終了後にseeds.txt(md5=0cf5051d586e7f62c0b3527f6f7fbb1c)を公開
入力生成方法
L 以上 U 以下の整数値を一様ランダムに生成する関数を \mathrm{rand}(L,U) で表す。 まずはじめに、2つのパラメータ D=\mathrm{rand}(100, 2000) と M=\mathrm{rand}(1, 2) を生成する。 頂点 (i, j) と (i,j+1) を結ぶ辺の長さを h_{i,j}、頂点 (i, j) と (i+1,j) を結ぶ辺の長さを v_{i,j} とする。
h_{i,j} の生成
- 各 i\in\{0,\ldots,29\}, p\in\{0,\ldots,M-1\} に対して独立に乱数値 H_{i,p}=\mathrm{rand}(1000+D,9000-D) を生成する。
- 各 i\in\{0,\ldots,29\}, j\in\{0,\ldots,28\} に対して独立に乱数値 \delta_{i,j}=\mathrm{rand}(-D,D) を生成する。
- M=1 の場合は、各 i\in\{0,\ldots,29\}, j\in\{0,\ldots,28\} に対して h_{i,j}=H_{i,0}+\delta_{i,j} と設定する。
- M=2 の場合は、各 i\in\{0,\ldots,29\} に対して乱数 x_i=\mathrm{rand}(1,28) を生成し、j\in\{0,\ldots,x_i-1\} に対しては h_{i,j}=H_{i,0}+\delta_{i,j}、j\in\{x_i,\ldots,28\} に対しては h_{i,j}=H_{i,1}+\delta_{i,j} と設定する。
v_{i,j} の生成
- 各 j\in\{0,\ldots,29\}, p\in\{0,\ldots,M-1\} に対して独立に乱数値 V_{j,p}=\mathrm{rand}(1000+D,9000-D) を生成する。
- 各 i\in\{0,\ldots,28\}, j\in\{0,\ldots,29\} に対して独立に乱数値 \gamma_{i,j}=\mathrm{rand}(-D,D) を生成する。
- M=1 の場合は、各 j\in\{0,\ldots,29\}, i\in\{0,\ldots,28\} に対して v_{i,j}=V_{j,0}+\gamma_{i,j} と設定する。
- M=2 の場合は、各 j\in\{0,\ldots,29\} に対して乱数 y_j=\mathrm{rand}(1,28) を生成し、i\in\{0,\ldots,y_j-1\} に対しては v_{i,j}=V_{j,0}+\gamma_{i,j}、i\in\{y_j,\ldots,28\} に対しては v_{i,j}=V_{j,1}+\gamma_{i,j} と設定する。
s_k, t_k の生成
クエリで与えられる頂点 s_kとt_k は、全ての頂点の中から一様ランダムに選択される。 s_k と t_k のマンハッタン距離 |si_k-ti_k|+|sj_k-tj_k| が10未満の場合は、10以上になるまで選択を繰り返す。
ツール
- ローカルテスタ: 使用するには、Rust 言語のコンパイル環境をご用意下さい。
- ビジュアライザ
- 入力データ: 上のローカルテスタを使用しない場合は、こちらのローカルテスト用の100個の入力データ(seed 0-99)を利用することも出来ます。これらの入力は実際のテストケースとは異なります。入力データは以下のフォーマットとなっており、各自でジャッジ用のプログラムを書いてご利用下さい。
h_{0,0} \ldots h_{0,28} \vdots h_{29,0} \ldots h_{29,28} v_{0,0} \ldots v_{0,29} \vdots v_{28,0} \ldots v_{28,29} si_1 sj_1 ti_1 tj_1 a_1 e_1 \vdots si_{1000} sj_{1000} ti_{1000} tj_{1000} a_{1000} e_{1000}
ジャッジ用プログラムの例(疑似コード)
string query(s, t, prev_result) { // WRITE YOUR SOLUTION HERE } int main() { if (LOCAL_TEST) { read_h_v(); } prev_result = 0; score = 0.0; for (int k = 0; k < 1000; k++) { if (LOCAL_TEST) { read_s_t_a_e(); } else { read_s_t(); } path = query(s, t, prev_result); print(path); if (LOCAL_TEST) { b = compute_path_length(path); score = score * 0.998 + a / b; prev_result = round(b * e); } else { prev_result = read_result(); } } if (LOCAL_TEST) { print(round(2312311 * score)); } return 0; }
Story
AtCoder is developing a route navigation application that utilizes shortest path algorithms. The service area is represented as a road network of 30x30 vertices connected in a grid. When a user specifies the vertex of the current location and the vertex of the destination, the app will output the shortest path between them. The trouble is that, even though the scheduled release date is approaching, the measurement of the length of each edge, which is essential for shortest path computations, is not finished at all. Therefore, AtCoder decided to give up measuring the edge length in advance and allows the app to output paths that are not the shortest. It should be possible to gradually improve the performance by estimating the length of each edge based on the information about the actual time users take to arrive at their destinations.
Problem Statement
There is an undirected grid graph with 30x30 vertices with unknown edge lengths. Let (0, 0) denote the top-left vertex, and (i, j) denote the vertex at the i-th row from the top and j-th column from the left. Your task is to process the following query 1000 times.
In the k-th query, your program first receives the vertices s_k=(si_k,sj_k) and t_k=(ti_k,tj_k) from Standard Input in the following format:
si_k sj_k ti_k tj_k
Then, your program should compute a path P_k from s_k to t_k.
Let U
, D
, L
, and R
represent the movement from (i,j) to (i-1,j), (i+1,j), (i,j-1), and (i,j+1), respectively.
Output a string representing the path P_k to Standard Output in one line.
After the output, you have to flush Standard Output. Otherwise, the submission might be judged as TLE.
After your program outputs a path, the judge program calculates the length b_k of the path, generates a uniform random number e_k between 0.9 and 1.1, and gives an integer value \mathrm{round}(b_k\times e_k) to Standard Input. By reading that integer, the k-th query completes, and you should proceed to the k+1-th query.
Examples
Input | Output |
---|---|
3 19 16 17 |
|
DDDDDDDDDDDDDLL |
|
99561 |
|
26 18 13 18 |
|
UUUUUUUUUUUUU |
|
72947 |
Scoring
Let a_k and b_k be the lengths of the shortest path and the output path for the k-th query (1\leq k\leq 1000), respectively. Then the score for the test case is
\mathrm{round}(2312311\times \sum_{k=1}^{1000}0.998^{1000-k} \frac{a_k}{b_k})
The score of a submission is the total score for each test case.
If your program outputs an illegal path (visiting the same vertex multiple times, going outside of 30x30, or not a path from s to t), it is judged as WA
.
After the contest is over, the final ranking will be determined by system tests against the last submission.
- Provisional tests consist of 100 test cases. If you get a result other than
AC
for one or more test cases, the score of the submission will be zero. - System tests consist of 3000 test cases. If you get a result other than
AC
for some test cases, only the score for those test cases will be zero. We will publish seeds.txt (md5=0cf5051d586e7f62c0b3527f6f7fbb1c) after the contest is over.
Input Generation
Let \mathrm{rand}(L,U) be a function that generates a uniformly random integer between L and U, inclusive. We first generate two parameters D=\mathrm{rand}(100, 2000) and M=\mathrm{rand}(1, 2). Let h_{i,j} be the length of the edge between (i, j) and (i,j+1), and let v_{i,j} be the length of the edge between (i, j) and (i+1,j).
Generation of h_{i,j}
- For each i\in\{0,\ldots,29\} and p\in\{0,\ldots,M-1\}, we independently generate a random integer H_{i,p}=\mathrm{rand}(1000+D,9000-D).
- For each i\in\{0,\ldots,29\} and j\in\{0,\ldots,28\}, we independently generate a random integer \delta_{i,j}=\mathrm{rand}(-D,D).
- If M=1, for each i\in\{0,\ldots,29\} and j\in\{0,\ldots,28\}, we set h_{i,j}=H_{i,0}+\delta_{i,j}.
- If M=2, for each i\in\{0,\ldots,29\}, we generate a random integer x_i=\mathrm{rand}(1,28), and then for each j\in\{0,\ldots,x_i-1\}, we set h_{i,j}=H_{i,0}+\delta_{i,j}, and for each j\in\{x_i,\ldots,28\}, we set h_{i,j}=H_{i,1}+\delta_{i,j}.
Generation of v_{i,j}
- For each j\in\{0,\ldots,29\} and p\in\{0,\ldots,M-1\}, we independently generate a random integer V_{j,p}=\mathrm{rand}(1000+D,9000-D).
- For each i\in\{0,\ldots,28\} and j\in\{0,\ldots,29\}, we independently generate a random integer \gamma_{i,j}=\mathrm{rand}(-D,D).
- If M=1, for each j\in\{0,\ldots,29\} and i\in\{0,\ldots,28\}, we set v_{i,j}=V_{j,0}+\gamma_{i,j}.
- If M=2, for each j\in\{0,\ldots,29\}, we generate a random integer y_j=\mathrm{rand}(1,28), and then for each i\in\{0,\ldots,y_j-1\}, we set v_{i,j}=V_{j,0}+\gamma_{i,j}, and for each i\in\{y_j,\ldots,28\}, we set v_{i,j}=V_{j,1}+\gamma_{i,j}.
Generation of s_k, t_k
The vertices s_k and t_k given in the query are chosen uniformly at random among all the vertices. If the Manhattan distance between s_k and t_k (|si_k-ti_k|+|sj_k-tj_k|) is strictly less than 10, we repeat the random selection until the distance becomes at least 10.
Tools
- Local tester: You need a compilation environment of Rust language.
- Visualizer
- Inputs: If you don't use the above local tester, you can instead use these 100 inputs (seed 0-99) for local testing. These inputs are different from the actual test cases. The inputs are in the following format, and you can use them by writing a judge program by yourself.
h_{0,0} \ldots h_{0,28} \vdots h_{29,0} \ldots h_{29,28} v_{0,0} \ldots v_{0,29} \vdots v_{28,0} \ldots v_{28,29} si_1 sj_1 ti_1 tj_1 a_1 e_1 \vdots si_{1000} sj_{1000} ti_{1000} tj_{1000} a_{1000} e_{1000}
Example of judge program (pseudo code)
string query(s, t, prev_result) { // WRITE YOUR SOLUTION HERE } int main() { if (LOCAL_TEST) { read_h_v(); } prev_result = 0; score = 0.0; for (int k = 0; k < 1000; k++) { if (LOCAL_TEST) { read_s_t_a_e(); } else { read_s_t(); } path = query(s, t, prev_result); print(path); if (LOCAL_TEST) { b = compute_path_length(path); score = score * 0.998 + a / b; prev_result = round(b * e); } else { prev_result = read_result(); } } if (LOCAL_TEST) { print(round(2312311 * score)); } return 0; }