at coder regular contest 013 解説

26
AtCoder Regular Contest 013 解解 解解解解解 @hamayanhamayan

Upload: hamayanhamayan

Post on 14-Apr-2017

207 views

Category:

Engineering


3 download

TRANSCRIPT

Page 1: At coder regular contest 013 解説

AtCoder Regular Contest 013解説非公式解説

@hamayanhamayan

Page 2: At coder regular contest 013 解説

#A梱包できるかな?

Page 3: At coder regular contest 013 解説

問題概要• サイズ N × M × L のダンボールにサイズ P × Q × R の荷物を出来るだけ詰め込む• 詰め込むときに荷物を 90 度倒しても良い• ダンボールに詰め込める荷物の最大個数は?• 1 N,M,L 100≦ ≦• 1 P,Q,R 100≦ ≦

Page 4: At coder regular contest 013 解説

解法• 荷物を回転させると 6 パターンできる• (縦 , 横 , 高さ)= ( P, Q, R ) , ( P, R, Q ) , ( Q, P, R )•         ( Q, R, P ) , ( R, P, Q ) , ( R, Q, P )• 全部で詰める荷物の数を計算し、最大値を出力• 計算式は (N / P) * (M / Q) * (L / R)• 除算部分は整数計算で小数点以下を切り捨てさせる

Page 5: At coder regular contest 013 解説

#B引越しできるかな?

Page 6: At coder regular contest 013 解説

問題概要• i 個目の大きさがそれぞれ Ni × Mi × Li である荷物が C 個ある• この荷物から 1 つ選んで、直方体のダンボールに入れるとする• この時、どの荷物を選んでも入れることができるダンボールの容積の最小値は?• 90 度単位での回転は許される• 1 C 100≦ ≦• 1 N, M, L 100≦ ≦

• 部分点• 1 C 10 ≦ ≦ を満たす入力に正解すると 40 点

Page 7: At coder regular contest 013 解説

部分点解法• 思いつかない

Page 8: At coder regular contest 013 解説

解法• ダンボールがあった時に荷物が入るかどうか確認する時は、

• 荷物の 1 番目に長い辺 ≦ ダンボールの 1 番目に長い辺• 荷物の 2 番目に長い辺 ≦ ダンボールの 2 番目に長い辺• 荷物の 3 番目に長い辺 ≦ ダンボールの 3 番目に長い辺

• を満たせば入ることが分かる• つまり、各荷物に対して、上の条件が満たされるようにサイズを拡張していく• 具体的には

• ダンボールのサイズを 0 × 0 × 0 (N = 0, M = 0, L = 0) で初期化• 各荷物 i に対して• Ni , Mi , Li をソートして一番長い辺を Ni 、二番目を Mi 、三番目を Li とする• N = max(N, Ni), M = max(M, Mi), L = max(L, Li) で更新• N * M * L が答え

Page 9: At coder regular contest 013 解説

#C笑いをとれるかな?

Page 10: At coder regular contest 013 解説

問題概要• N 個の豆腐があり、それぞれ以下の情報が与えられる

• 豆腐の縦の長さ X 、横の長さ Y 、高さ Z• 豆腐に含まれるハバネロの個数 M• ハバネロの位置 (x, y, z) が M 個分

• この時、高橋くんと青木くんが以下のルールでゲームを行う• 先攻は青木くん• 自分の番では、豆腐を 1 つ選んで下図の切り方で切り、どちらかを食べる• もし食べた中にハバネロが含まれていたら負け

Page 11: At coder regular contest 013 解説

問題概要• 高橋くんと青木くんがハバネロの位置を把握していて、互いに最適な行動を行うときに

• 高橋くんが勝つなら” WIN”• 高橋くんが負けるなら” LOSE”• を出力

• 1 N 1000≦ ≦• 1 X, Y, Z 10^9≦ ≦• 1 M 100≦ ≦• 0 x X-1≦ ≦    0 y Y-1≦ ≦    0 z Z-1≦ ≦

• 部分点• N = 1 かつ 1 X, Y, Z 20 ≦ ≦ を満たす入力に正解すると 30 点

Page 12: At coder regular contest 013 解説

部分点解法• Nim 問題を排他的論理和以外で解く方法を• 知らないので書けないです…• 深さ優先探索とかで書ける?

Page 13: At coder regular contest 013 解説

必要知識• この問題は「勝敗判定系問題」特有の知識が必要です• http://d.hatena.ne.jp/nanikaka/20120524/1337797626• 上のサイトがとても参考になります Nim • K 個のコインの山があり、各山には n1, … , nK 個のコインがある• 2 人のプレイヤーは交互に好きな山から 1 枚以上のコインを取る• 最後の 1 枚を取ったプレイヤーの勝ち• この Nim の勝敗はコインの数の排他的論理和 xor を計算すると分かる• n1 xor … xor nK が 0 なら後手の勝ち、 1 なら先手の勝ち

Page 14: At coder regular contest 013 解説

考察• 今回の問題は実質 Nim と同じ問題と考えることができる• 両者とも最善の行動を取れば、各豆腐はハバネロが全て収まる最小サイズまで削られる• 各豆腐をそのサイズまで削る為に、 x 軸 ,y 軸 ,z 軸のそれぞれ両側から無駄な部分を互いに 1 つ以上削り合っていく事になる• 6 つの山からコインを 1 枚以上取っていくことと同じである• つまり

• N 個の豆腐 → 4N 個の山• 無駄な部分として削れる個数 → 山にあるコインの枚数

• として考えて、 Nim として解くことができる

Page 15: At coder regular contest 013 解説

解法• 各豆腐に対して、ハバネロが全て収まる最小領域を計算する

• 最小領域を (sx ~ ex, sy ~ ey, sz ~ ez) とすると• sx はハバネロの各座標 x の最小値、 sy, sz も同様• ez はハバネロの各座標 x の最大値、 ey, ez も同様

• 無駄な部分として削ることができる部分を xor していく• x 軸方向で無駄な部分の数は、 sx 個と (X – 1 - ex) 個 なのでこれを xor• y 軸方向、 z 軸方向も同様

• 全て xor した結果が• 0 ならば “ LOSE”• 0 でないなら “ WIN”

Page 16: At coder regular contest 013 解説

#D切り分けできるかな?

Page 17: At coder regular contest 013 解説

問題概要• N 種類の鉄塊があり、それぞれ、縦 (X)× 横 (Y)× 高さ (Z) が与えられる• 1 つの鉄塊につき、丁度 1 回右図のように切り分ける• 全ての鉄塊の体積のパターンをそれぞれ 2 つ以上作るためには、何個の鉄塊が最低必要だろうか?• 1 N 100≦ ≦• 1 X, Y, Z 20≦ ≦

• 部分点• N = 1 を満たす入力に正解すると 20 点

Page 18: At coder regular contest 013 解説

部分点解法• 直感的にやってみる• まず、 2 つに分けると出来るパターンを全パターン作る• これは set あたりを使ってやると良い• 次に、全パターンを 2 回やったとして出来る体積毎に個数をカウントする• すると、全個数必ず 2 個以上作られることになる• 最後に、全パターンに対して、出来るどちらの体積も 3 個以上作られているものを引けなくなるまで引いて答えとする

Page 19: At coder regular contest 013 解説

部分点解法• これで一応、部分点はもらえました• もらえたけど、かなりヒューリスティックな解法• 近似解ではあるけど厳密解ではない(実際、沢山 WA が出る)• 全く解法が思いつかないのであれば、このような博打的方法でもいいのかも• (これ以外の部分点解法あればご教授ください…)• http://arc013.contest.atcoder.jp/submissions/551709

Page 20: At coder regular contest 013 解説

考察例)切断して出来る体積の組が {1,2}, {1,3}, {1,4} とする

1234

1234

右図のようにグラフにして考えてみるこうすると、各パターンが 2 個以上作られるということは「左側と右側がそれぞれ 1 回以上使われるような最小の辺をとる」ことになる

1234

1234

この例では全部の辺を用いるパターンである。よって、この例の答えは 6

Page 21: At coder regular contest 013 解説

考察• この状況に似た問題がある 「 2 部グラフの最大マッチング問題」

• 2 部グラフとは、両端に頂点があり、片側から片側にのみ辺があるグラフ• マッチングとは、端点を他と共有しない辺のこと• 最大マッチング問題とは、マッチングの数を最大にするように辺をとる問題のこと

• 右図で言うと、緑の辺が最大マッチングの 1例• http://mathtrain.jp/bipartitematching

• とても詳しく書いてある• 右図もこちらから

Page 22: At coder regular contest 013 解説

考察今回の問題は最大マッチング問題とは少し違う

1234

1234

例のグラフで最大マッチングを行うとこうなる両端の 3 と 4 が繋がっていないので、この 4 つの頂点を追加すれば答えになりそう

• 全部で N パターン出来るとすると、 2 部グラフの頂点は 2N 個• 最大マッチング数を M とすると、つながっている頂点は 2M 個• より、つながっていない頂点は 2N - 2M

• より求めたい答えは、 M + (2N – 2M) = 2N – M で求められる

Page 23: At coder regular contest 013 解説

考察• 2 部グラフの最大マッチングは「最大フロー問題」に帰着できる

• 個人的に最大フロー問題に帰着させた方がいいと思ってる

• Wikipedia 「最大フロー問題」• 右図のようにコスト(水を流せる量)が決まっている有向グラフに対して、 sから tへ流せる最大コスト(流量)を求める問題• フォード・ファルカーソン法で解く• 詳しくは省略

Page 24: At coder regular contest 013 解説

考察• 2 部グラフの最大マッチング問題 → 最大フロー問題

• 2 部グラフの左側に頂点 s を作り、全ての左側の頂点に辺を作る• 同様に右側に頂点 t を作り、全ての右側の頂点に辺を作る• 全ての辺の最大コストを 1 とする• この時得られる最大フローは、元の最大マッチング数と等価

s t

Page 25: At coder regular contest 013 解説

解法• 2 つに分ける全パターン作る

• この時、 2 部グラフの頂点とするべき数も別に集計しておく

• グラフを作る• 頂点を作る時は左側と右側が同じラベルの頂点だと扱いづらいので、右側の数は +8000 した数としておく (8000 は体積の最大値 )• s は体積 0 、 t は体積 16000 として定義し、 s から左側、右側から t の辺を追加しておく

• 作ったグラフで最大フロー問題を解く• 「作れる体積の全パターン数 * 2 – 最大マッチング数」が答え

Page 26: At coder regular contest 013 解説

謝辞• D 問題は自力で解けなくて、以下のサイトを参考に作りました• 解説を上げてるコーダーの方々にはいつもお世話になってます• http://kmjp.hatenablog.jp/entry/2014/03/12/1000• http://d.hatena.ne.jp/oupo/20130702/1372749407

• 今回は解法全然分からなくて、しかも、理解も難しくてかなりしんどかったです• 上の参考にした blog の記事もちゃんと理解してる気がしないです