目次> 第20章> 20.3 TOPUPPREVNEXT

20.3 エイト・クィーンの問題

プログラミング入門の定番です。
リカーシブ・アルゴリズムの例題として提示されることも多いのですが、 全数探索の例題としてもよく使われます。

「すべてのケースを洗い出して調べてみる」 しかないと考えられる問題で、

といったことが、重要になります。

[エイト・クィーンの問題]

チェスのクィーンのコマは、縦、横、斜めにいくつでも進めます。 コマが進める場所に敵のコマがあると獲ることができ、したがって、 コマの進める場所を利き筋といいます。 例えば、下図のように(0から数えて)1行目の2列目にクィーンがある場合、黄色の部分が このクィーンの利き筋です。

チェス盤は、縦8、横8の盤ですが、ここに8個のクィーンをお互いに 利き筋にないように置く
というのが問題です。

チェス盤を一般化して、縦横Nマスの盤にN個のクィーンを置く問題を N−Queen問題といいます。この問題は、Nが増加するにつれて 計算の手間が、N に比例して増加することで 知られています。Nが8とか10であればあっという間に計算できますが、 Nが大きくなるにつれて計算時間が急激に増加します。 このように、問題のサイズが大きくなるにつれて 計算時間が指数関数的に増加する問題をNP問題といいます。

「計算」という用語に違和感があるかもしれませんが、コンピュータの処理の ことです。計算量理論とか、アルゴリズムの分野での用語です。
NP ... nondeterministic polynomial

20.2のハノイの塔は、円盤の個数nに対して、移動回数が 2 − 1 ですから、これもNP問題です。

チェス盤や駒のイメージがわかないかたは こちらの写真 はいかがですか。

 20.3.1 アルゴリズム

概ね、以下の戦略ですべての組み合わせを網羅します。

Java の メソッド風の書き方で、 「 n 行目に置く」 という checkAndSet( n ) を書いてみましょう。 n 行目の置ける場所を探すには、n 行目以降 一番下まで ちゃんと置けることを確認しなければいけません。
行は 0、1、2、...、7 までの8行です。

void checkAndSet(int n) {

}

n行目の k列目にクイーンを置くことを

pos[n] = k;

と表しましょう。たとえば、pos が { 0, 4, 7, 5, 2, 6, 1, 3 } であれば、下図のような盤とクイーンの配置を表すことにします。

最初の解

クイーンの縦の利き筋は、posに同じ番号がないかどうかで調べられます。 右上がり方向の利き筋は、 行と列の和が等しいことで調べられます。 右下がり方向の利き筋は、 行と列の差が等しいかどうかで調べられます。クイーンを置いたときに、 列の番号をposに保存すると同時に、行番号から列番号を引いたものを na に 行番号と列番号の和を ns に設定しておくことにします。

 20.3.2 プログラム

行番号つきプログラム・リスト

ソースプログラムは、 EightQueen4.java です。

実行には、次の4つの GIF ファイルが必要です。プログラムと同じフォールダにダウンロードしてください。

queen-on.gif
queen-off.gif
queen-chk.gif
queen-try.gif


更新日:2004-06-25 TOPUPPREVNEXT