第1回 岩井星人アンソロジープログラミングコンテストはYouTubeで競技プログラミングの実況を行っている岩井星人さんを題材にした問題のみを出題するコンテストです。ちなみに岩井星人さんはこんな方です。

「鎖国派最後の生き残り♪令和の大政翼賛会♪」なんて言っちゃってますが、真に右寄りな方ではないのでご安心ください。

ではさっそくいってみましょう。

No.3010 水色コーダーさん

問題文はこちらです ⇒ No.3010 水色コーダーさん

この問題は、R_i が 1200 以上の場合、S_i の先頭4文字が “oooo” でなかった場合に気絶すると考えてよいので以下のようなコードになります。

No.3011 あ、俺こいつの役やりたい!

問題文はこちらです ⇒ No.3011 あ、俺こいつの役やりたい!

この問題はインタラクティブな問題(あなたの作成したプログラムとジャッジシステムが入出力を介して対話を行う形式の問題)です。

予算である N 以下の値を出力してしまった段階で即終了となり、しかも

N が報酬の 2 倍以下、別の言い方をすると最後に出力した値が N の半分以上になるようにしなければならないので最初は N が取りうる最大値(10の9乗)を出力して 0 が入力されるたびに半分の値を出力し続ければ正解となります(10の9乗が2の30乗より小さいため)。

No.3012 岩井星人グラフ

問題文はこちらです ⇒ No.3012 岩井星人グラフ

要はこんなグラフを出力すればよいのです(ただし頂点番号は0-indexed。回答を出力するときは1-indexedにしないといけないので注意)。

長さがYの腕を先にX本つくります。頂点を番号を0はじまりだとすれば腕の付け根の番号は Yの倍数です。以降の頂点を番号が次のYの倍数より1少ない値になるまで直線上につなげます。最後に腕の付け根を環状に連結します。

No.3013 ハチマキ買い星人

問題文はこちらです ⇒ No.3013 ハチマキ買い星人

移動するとカツアゲされて残金が減ります。なのであまりカツアゲされないうちに近くて買ってしまうほうがよいか、それとも多少カツアゲされても安くハチマキを買うことができる店まで移動するか、という問題です。これはカツアゲされる合計を頂点までの移動コストと考えて、店がある頂点で残金でどれだけハチマキを買えるかを考えればよいです。またハチマキはすべて同じ店で買います。複数の店で買っても同じ店で買うよりよい解を得ることはできないからです。

失敗例 ダイクストラ法ではなくただの幅優先探索

ダイクストラ法ではなくただの幅優先探索で解こうとすると制限時間以内に処理は終わりません。

普通の幅優先探索と異なりダイクストラ法は

始点から移動可能な頂点への移動コストの暫定値を計算・記憶しておき、そのなかから最小のものを取り出します。辺の重みがすべて非負数であればその値が更新されることはないので確定させる。移動コストが確定した頂点から移動可能な頂点から移動できる頂点への移動コストの暫定値を計算する……という処理を繰り返す

という方法です。こうすることで無駄な探索と値の更新をなくしています。そしてキューのなかから移動コストが最小のものを取り出すためには優先度付きキュー(PriorityQueue)を使わなければなりません。

失敗例 正しくないダイクストラ法

ただし上記コードのQueueをPriorityQueueに取り替えただけでは不十分です。TLE(時間切れ)の件数は減りましたが、やはりすべてのテストケースを通すことができません。

正解例 正しいダイクストラ法

ダイクストラ法では、始点から移動可能な頂点への移動コストの暫定値を計算・記憶しておき、そのなかから最小のものを取り出し、この値を確定させます。確定したあとであってもPriorityQueueから同じ頂点への移動コストに関する情報は取り出され続けるので、確定後はそれらは無視しなければなりまん。そうでないと無駄な処理が発生して制限時間以内に終わりません。

No.3014 岩井満足性問題

問題文はこちらです ⇒ No.3014 岩井満足性問題

動的計画法の問題ですが、単純なナップサック問題とちがって満足度と美しさというふたつの要素があります。そこで最初は2次元配列ではなく3次元配列を用いた方法を考えてみることにします。

メモリー制限に引っかかって不正解

以下のコードはやり方はあっているはずなのですが、メモリー制限に引っかかって不正解です。

正解例

3次元配列の各行は次の行の値が確定したら使わないので2次元配列で済むように書き換えます。

No.3015 右に寄せろ!

問題文はこちらです ⇒ No.3015 右に寄せろ!

これは文字列の中の 110 という連続部分列を 011 に変える操作が何回できるかを数える問題です。

110 を 011 に変えることで 0 の位置が右に 2 つ移動します。なので 0 を何回右に 2 つ移動できるかを数えます。

そのためには 0 の位置をリストに格納して、位置が小さいものから何回 2 を引くことができるかを数えます。このとき indexs[i] から 2 を引くことで 0 を下回ったり indexs[i-1] が存在する場合はこれ以下の値にならないように注意します。

No.3016 ハチマキおじさん

問題文はこちらです ⇒ No.3016 ハチマキおじさん

配列 A と B があり、A の長さのほうが 1 大きいです。このとき、|A[i] – B[j]| の総和を最小化するにはどうすればいいかを問う問題です。

もし A と B が同じ長さなら A と B をソートしてあとは添字が同じもの同士を計算すればよいです。問題では A のほうが 1 長いのでどれを取り除くと総和を最小化することができるかを考えるのですが、実は A[0] を取り除いたときの総和がわかれば、この値を利用して A[1] を取り除いたときの総和を求める簡単な方法があるのです。

A[0] を取り除いたときの総和とは、|A[1] – B[0]| + |A[2] – B[1]| + |A[3] – B[2]| + |A[4] – B[3]| + … ですが、これに |A[0] – B[0]| を足して |A[1] – B[0]| を引けば A[1] を取り除いたときの総和になるのです。

No.3017 交互浴

問題文はこちらです ⇒ No.3017 交互浴

温泉に入ることで身体の色が塗り替えられていきます。水色の部分の長さを求めよという問題です。

塗り替えられた長さをStackに追加していくのですが、そのまえに前の色が新しい色で完全に塗り替えられるのであればその部分は同じ色でも異なる色でもStackから削除します。Stackから削除した結果、前の色と新しい色が同じ場合は追加しません。Stackへの追加と削除が繰り返されるたびに ans の値を加除します。

途中でStackが空になってしまうと処理が面倒になるので、最初に 10^9 + 1 の長さで緑色に塗っておきます。問題文では最初は岩井星人さんの身体は全身が緑色であることと、色が変わるのは 10^9 までなのでこれでも問題はありません。

No.3018 目隠し宝探し

問題文はこちらです ⇒ No.3018 目隠し宝探し

この問題はインタラクティブな問題(あなたの作成したプログラムとジャッジシステムが入出力を介して対話を行う形式の問題)です。基本的に質問は2回で宝物の位置を特定できます。またグリッドのサイズによっては質問は1回だけ、または0回で宝物の位置を特定できる場合があります。この場合は質問回数がそれよりも多いと不正解になってしまいます。

グリッドの幅と高さが両方とも 1 の場合は質問しなくても宝物の位置は特定されます。それ以外の場合は左上から宝物までのユークリッド距離の 2 乗を質問します。そしてグリッド上を全探索して該当するマスを列挙します。もしそのようなマスがひとつに限定されたら処理は終了です。ひとつに限定されなかった場合は続いて右上から宝物までのユークリッド距離の 2 乗を質問します。これで宝物があるマスは必ずひとつに限定されます。宝物があるマスが特定されたらその座標を出力するだけです。