2019/2020 日本情報オリンピック(JOI)2次予選参加記
お疲れさまです。ABC3完とD部分点で330点でした
- A - ポスター (Poster)
- B - いちご (Strawberry)
- C - 桁和 (Digit Sum)
- D - テンキー (Tenkey)
- E - じゃんけん式 (Rock-Scissors-Paper Expression)
- 感想
A - ポスター (Poster)
行列の大きさのポスターがあり、それぞれのマス3色で塗られている。このポスター をポスター の配色にしたい。次の3つの操作をコスト で何回でもできる:
- 好きなマス一つを好きな色に塗る
- ポスターを時計回りに 度回す
- ポスターを反時計回りに 度回す
を にするためにかかる最小コストを求めよ。
考察・解法・実装など
どの操作をどの順番で行っても結果は同じなので、先に を回転させる操作を終わらせればあとはマスを の色に塗るだけ。 の回転させ方はたかだか4通りなので全部シュミレーションする。
B - いちご (Strawberry)
いちごが 個ある。いちご は地点 にあり、 分後に熟す。収穫するのにかかる時間は 分である。熟す前は収穫できない。
地点 からスタートし、隣り合う地点を移動するのに 分かかる。全部のいちごを収穫して地点 まで戻るのに最短で何分かかるか。
考察・解法・実装など
どのように動いても地点 から一番遠いいちごのある地点 までは移動しなければならないので、とりあえず地点 に移動し、地点 から地点 に戻るまでの道中でいちごを収穫するというルールを作るとわかりやすい。具体的には、常に負の方向(地点 の方向)に進みつつ、いちごがある地点まで来たらいちごを収穫し、この時まだ熟していなければその場で熟すまで待つ、というような貪欲法で解ける。
C - 桁和 (Digit Sum)
以上 以下の整数のうち、以下の条件を満たすものはいくつあるか。
- 「現在の数の各桁の和を現在の数に足して値を更新する」という操作を 回以上行ったとき になる
D - テンキー (Tenkey)
テンキー(電卓などでよく見る、 が左下にある配置のもの)とテンキー中の数字を指し示すカーソルがある。カーソルは最初 を指している。テンキー上で次の二つの操作をコスト で何回でもできる:
- カーソルを上下左右好きな方向に マス分動かす
- カーソルが指している数字を入力する。すでに文字が入力されている場合、その数字列の最後尾に追加する。
で割って 余るような数を一つ入力するためにかかる最小コストを求めよ。
小課題(点):
考察・解法・実装など
入力する数を とすると、 が成り立つ。
まずは小課題について考える。小課題の制約が ちょうどで、 は最大でも 桁であることを考えると、 として とするのが望ましいことがわかる( の候補を書き出してみるとわかるが、下から数桁は常に同じ数列であり、 が増えるごとに上位桁の分を余計に入力しなければならなくなる)。実装については、各数字について「一つ前に入力した数字の位置と今入力したい数字の位置のマンハッタン距離」と「数字を入力するためのコスト」の総和を求める関数を組めばよい。ある一桁の数字を指定したとき、その座標がすぐ求まるようにすると良い。
小課題の制約がないパターンの解法は未だわからない。解法を求めて読んでいる人には申し訳ないがほかのサイトをあたってください。 の値を ~ 程度まで全探索するコードを提出したが、WAが出てしまった。貪欲や全探索ではなさそうで、テンキーの配置の特性を利用した解法、というのも考えづらい。テンキーを押す回数 を固定したときに押せる数を列挙してその中に があるか探す、というのも考えたが、 の最大値が である(例えば を入力したときなど)のでこちらはTLEしそうである。
E - じゃんけん式 (Rock-Scissors-Paper Expression)
じゃんけんの手 R
S
P
と独自の演算+
-
*
と括弧 (
)
から成るじゃんけん式を考える。じゃんけん式の中でじゃんけんの手がいくつか ?
に変えられている。長さ のじゃんけん式 の答えが となるような ?
の埋め方は何通りあるか、 で割った余りを答えよ。
は正しいじゃんけん式
小課題1( 点):
小課題2( 点):
考察・解法・実装など
小課題も解けなかった。これがいわゆる構文解析の問題であるのは分かっているが、構文解析をしたことがなかった。一応時間いっぱいまで粘ってみたものの、WAが出てしまった。
まず ?
が登場しない式を考える。 の先頭と末尾にそれぞれ (
と )
を付けて考えると、一番内側の括弧の中の式には +
-
*
の演算だけが登場する(ほかの括弧の存在を気にする必要がない)。*
の方が優先度が高く、優先度が高い演算は前から処理するという規則より、*
を計算してから +
-
を計算することで括弧内の式を一つのじゃんけんの手とすることが出来る(はず)。これを内側から処理していけば最終的に式全体を一つの手とすることが出来る。計算量が少し怪しい(になりそう)。
?
の扱いについて、?
を含む「じゃんけんの手」を この手がとなるような組み合わせの総数この手がとなるような組み合わせの総数この手がとなるような組み合わせの総数 とする。R
を 、?
を という風に置くとうまくいきそうだと考えた。あとは上記の考察を拡張して、最終的なじゃんけんの手の の部分を出力すればよい。
これを実装して提出したがWAが出た。実行時間は72msだったので、単純な実装ミスか、もっといい解法が存在するかの2択である。
感想
個人的に解けそうで解けない少し解ける難易度の問題ばかりで楽しかった。JOI予選初参加だったが、既に高3の年齢なので本選出場資格はなかった…。