エイトクイーンの問題
バックトラッキングアルゴリズムの古典的なケース
バックトラッキングアルゴリズムの典型的なケース。この問題は、1848年にチェスプレーヤーのMax Bethelによって提起されました。8つのクイーンを8X8のチェス盤に配置して、お互いに攻撃できないようにします。つまり、2つのクイーンが同じ行の外に出ることはできません。同じ列または同じ対角線で、いくつの方法があるか尋ねます。
思考分析
- 最初の女王は最初の行と最初の列に配置されます
- 2番目のクイーンを2番目の行の最初の列に配置し、0Kかどうかを判断します。問題がある場合は、引き続き2番目と3番目の列に配置し、すべての列を順番に並べて、適切なものを見つけます。
- 3番目の女王に進み、1列目と2列目を失神させます... 8番目の女王が競合しない位置に配置できるようになるまで、正しい解決策が見つかったと見なされます。
- 正しい解が得られたとき、スタックが前のスタックにロールバックすると、それはバックトラックを開始します。つまり、最初の女王は、すべての正しい解を最初の列に入れ、すべてを取得します。
- 次に、戻って最初の列に進みます。2番目のクイーンを2番目の列に配置してから、手順1、2、および3を繰り返します。
**説明:**理論的には、チェス盤を表すために2次元配列を作成する必要がありますが、実際には、1次元配列を使用してアルゴリズムを通じて問題を解決できます。arr[8] = {0,4 、7、5、2、6、1、3)は正の解を表します
対応するarr添え字は行数、つまりクイーンの数を示します。arr[i] = val、valはi +1番目の行のval + 1番目の列に配置されたi + 1番目のクイーンを示します。
効率は比較的低い可能性があり、欲張りアルゴリズムなど、後で最適化するアルゴリズムもあります。これについては、次の注記で説明します。
コード
package com.wang.Recursion;
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/20 19:45
* @Description TODO
* @pojectname 八皇后问题
*/
public class Queue8 {
//定义一个max表示共有多少个皇后
int max = 8;
//定义数组array,保存皇后放置的位置,比如arr[8]={0,4,7,5,2,6, 1,3}
int[] array = new int[max];
static int count = 0;
public static void main(String[] args) {
//测试
Queue8 queue8 = new Queue8();
queue8.check(0);
System.out.println("一共有"+count+"次解法");
}
//编写一个方法,放置第n个皇后
//特别注意:check是每一层递归时,进入到check都有for循环,因此会有回溯
private void check(int n){
//如果n = max,皇后放完了,
if (n == max){
print();
return;
}
//没有放完的话,依次放入皇后,判断是否冲突
for (int i = 0; i < max ; i++) {
//先把当前的皇后n,放到改行的第一列
array[n] = i;
//判断当放置了第n个皇后到i列时,是否冲突
if (judge(n)) {
//不冲突,接着放n+1个皇后,即开始递归
check(n+1);
}
//如果冲突,就继续执行array[n] = i;这个时候i已经++了,就是放到了下一列
}
}
/**
//查看当我们放置第n个皇后时,就去检测该皇后是否和前面已经摆好的皇后冲突
* @param n 表示第n个皇后
* @return
*/
private boolean judge(int n){
for (int i = 0; i <n ; i++) {
//array[i] == array[n]表示第n个皇后是否和前面i个皇后是否在同一列
//Math.abs(n-i) == Math.abs(array[n] - array[i]表示第n个皇后是否和第i个皇后在同一斜线
if (array[i] == array[n] ||Math.abs(n-i) == Math.abs(array[n] - array[i] )){
return false;
}
}
return true;
}
//将皇后拜访的位置打印出来
private void print(){
count++;
for (int i = 0; i <array.length ; i++) {
System.out.print(array[i]+"");
}
System.out.println();
}
}