はじめに
2021年4月入社の山田です、アルゴリズムとデータ構造連載の7日目です。
私は学生時代競技プログラミングに打ち込んでおりました。今回フューチャー技術ブログでアルゴリズムの記事を書く機会を頂きとても嬉しいです! よろしくお願いします!
内容
本記事では、最適化問題を解く上でのシンプルな高速化手法である monotone minima について説明します。
対象とする問題について紹介した後、 monotone minima のアルゴリズムの説明、そしてなぜ高速化が達成されるのかを説明します。
例題と問題の定式化
まず、イメージしやすいよう以下のような例題を考えてみます。
A市では大通り (ここでは
軸とします) に沿って 軒の家が並んでいます。 A市には 個のコンビニエンスストアが存在し、 軒の各家の住人はそれぞれ家に最も近いコンビニエンスストアを普段利用しています。 A市は家ごとにどのコンビニを普段利用しているかを調査することにしました。
家の座標
とコンビニの座標 が与えられるので、各家 についてどのコンビニを利用しているかを求めてください。
(簡単のため座標は、および が成り立つように並べられているものとします。)
簡単に図で例を示します。A市は2次元平面で表され、赤い丸が家、青い丸がコンビニを表しています。
それぞれの赤い丸
ここで、この問題はより一般的にこのように言い換えることができます。
関数
について、各 ごとに最小の値を実現する の値を求めてください。
(は整数 )
例題では
この問題は特に何も制約がない場合、
しかし、今回の例題のような場合には
monotone minima
では例題の関数
それは以下の性質です。
であるような任意の に対して、 の最小を与える を 、 の最小を与える を とした時に、 を満たす。
以降、これを性質
実際に先程図示した例で見てみましょう。 家とコンビニの距離
赤い文字で示されているところが最小値です。
(注:わかりやすいように実際には距離(ユークリッド距離)の2乗を示しています。)
これはどのような入力に対しても成り立ちます。
monotone minima は
monotone minima のアルゴリズムを擬似コードで以下に示します。
// i0 <= i <= i1 を満たす i について答えを求めていく関数 |
solve_all()
によって全ての
性質
高速化が達成される理由
では、これでなぜ高速化が達成されるのでしょうか? 問題の分割されていく流れに注目して計算にかかる時間を考えてみます。
始めは全く範囲が分割されていない状態からスタートします。
擬似コードにあったように、
次に一段階範囲を分割した(一段階再帰した)状態について見てみます。
分割されたそれぞれの範囲で
さらに分割して、
区間は4つに分かれましたが、やはり重複を無視して見ると
各分割で無視された重複箇所の合計は
これは
まとめ
今回は最適化問題を解くシンプルな高速化手法 monotone minima について説明しました。
monotone minima はシンプルながら強力な手法で、動的計画法への興味深い応用も存在します。
いずれ他の記事でそちらにも触れていけたらと思います。ありがとうございました!
参考リンク
週刊 spaghetti_source / Totally Monotone Matrix Searching (SMAWK algorithm)
Kyopro Encyclopedia of Algorithms / Monotone minima
動的計画法高速化テクニック(オフライン・オンライン変換)