アルゴリズム講座/実践編/分割統治 ホームページへ戻る 目次へ戻る
パズル問題解法のアルゴリズム講座

実践編

分割統治

 さて、実践編の第1段は「分割統治」です。このアルゴリズムの適用範囲はかなり限定されてしまいますが、使えた場合には大変感動的に「魔物」を体験できます。

1.分割統治の考え

   与えられた問題をいつくかの小問題に分割し、その一つ一つについて自分を再帰的に呼び出して
   解を求め、それらの解を結合(統治)することにより全体の解を求めます。先ほどの階乗を求める
   アルゴリズムも「分割統治」の例と言えそうです。
     Nの階乗を求めるには(問題)
     Nの値(これは自明)とN-1の階乗を求める問題に分割する(分割)
     N-1の階乗の解を自分を再帰的に呼び出して求める(再帰)
     Nの値とN-1の階乗の値をかけ合わせて全体の解を得る。(統治)
 

2.分割統治の適用制限

   幾つくかの小問題に分割出来なければ「分割統治」は使えません。さらに、
   自分とサイズが小さいだけの同種の問題に分割する必要があります。解かりやすい
   有名な例では、「ハノイの塔」や「クイックソート」があります。

3.「ハノイの塔」

   ここでは例題として「ハノイの塔」に挑戦してみます。

    3本の棒が立っています。ある棒にはn枚の
   ドーナツ型円盤が差し込んであります。
   この円盤を1枚ずつ移動してn枚総てを他の棒に
   移して下さい。ただし、小さい円盤の上に大きい
   円盤を置いてはいけません。

 
    この問題を「分割統治」で分析するとこうなります。

    n-1枚を目標外の棒に移し、残り1枚は目標の棒に移す。(n-1の問題)
    そして、先ほどのn-1枚を目標の棒に移す。(n-1の問題)
    尚、n-1枚の移動方法は自分を再帰的に呼び出して求める(再帰)
 


 
C言語ソースリスト

Java言語ソースリスト

Javaアプレットの実行

動きが判る様にウエイトをかけています。

   3本の棒に0,1,2と番号を付けてこんなプログラムが書けます。

    /* 1枚の円盤をaからbに移動するサブルーチン */
    void action(int a, int b) {
        省略
    }

    /* n枚の円盤をaからbに移動する */
    void puzzle(int n, int a, int b) {
        int c = 3 - a - b;    /* 目標外の棒 */

        if (n == 1) action(a,b);
        else {
            puzzle(n-1,a,c);  /* n-1の問題 */
            action(a,b);
            puzzle(n-1,c,b);  /* n-1の問題 */
        }
    }


目次へ戻る   前の頁へ戻る  次の頁へ進む