您的位置:首页 > 其它

巧解八皇后问题

2016-05-10 15:57 429 查看
问题描述:

在8*8的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一个斜线上,文有多少中解法?

问题分析:

如果用暴力求解发,则时间复杂度为:8*8的棋盘,一共有64个位置,有8为皇后,所以本质是将8位皇后放在64个位置上,即从64个位置中选择8个位置。所以总的搜索空间为:C864。

但是这个问题有很多限制条件,我们将这些限制条件加上之后,就可以大大的降低解空间:

同一行中不能放两个皇后,即每行只能放一个皇后。因此我们可以将8*8的矩阵缩减成一个8维的数组,表示一行只能放置一个皇后,其中数组的值表示:a[i] = j表示第i行在第j列上放置一个皇后;

然后我们需要用3个额外的辅助数组来保存列的放置情况,主对角线的放置情况,次对角线的放置情况:

一共8列,因此用一个8维的boolean型数组记录当前列是否有皇后已经放置;

对角线的问题略有复杂,但是仍然可以分析得出横纵坐标之间的关系:假设在我们放置皇后的数组中,a[3] = 2, 也就是说明:

对于主对角线来说:所有a[1][0], a[2][1], a[4][3], a[5][4], a[6][5], a[7][6]不能再放置皇后,可以发现他们横纵坐标的关系为:x-y=1始终成立,因此我们得出如果a[i] = j, 则所有i-j的位置都不能再放置皇后,而对于8*8的棋盘来说,-7<=x-y<=7, 即-(N-1)<=x-y<=N-1, 即 0<=x-y+N-1 <=2N-2,所以申请一个长度为2N-1的数组来记录主对角线的摆放情况;

对于次对角线来说:所有a[0][5], a[1][4], a[2][3], a[4][1], a[5][0]都不能再放置皇后,可以发现他们横纵坐标的关系为:x+y=5始终成立,因此我们得出如果a[i] = j,则所有i+j的位置都不能再放置皇后,而对于8*8的棋盘来说,0<=x+y<=2N-2,所以申请一个长度为2N-1的数组来记录次对角线的摆放情况。

用深度优先搜索的思路,每次走到一条思路或者终点,需要回溯。所以代码为:递归+回溯。

package com.eight;

import java.util.ArrayList;
import java.util.Arrays;

class EightQueen {
private int N; //The number of queens.
private boolean[] column;
private boolean[] maind;
private boolean[] secondaryd;
private ArrayList<int[]> result = new ArrayList<int[]>();

/**
* Initial the column, main diagonal, secondary diagonal to false,
* which means there is no queen everywhere.
* @param N
*/
public void initQ(int N) {
this.N = N;
column = new boolean
;
maind = new boolean[2 * N - 1];
secondaryd = new boolean[2 * N - 1];
int i = 0;
for(i=0; i<column.length; i++)
column[i] = false;
for(i=0; i<maind.length; i++)
maind[i] = false;
for(i=0; i<secondaryd.length; i++)
secondaryd[i] = false;
}

/**
* the main function of lay queens.
*/
public void queens() {
int[] path = new int
;
calcQueen(path, 0);
}

private void calcQueen(int[] path, int row) {
// TODO Auto-generated method stub
if(row == N) {
result.add(path);
System.out.println(Arrays.toString(path));
return;
}
for(int col=0; col<N; col++) {
if(canLay(row, col)) {
path[row] = col;
column[col] = true;
maind[row-col+N-1] = true;
secondaryd[row+col] = true;
calcQueen(path, row+1);

//BackTracking, important!!
column[col] = false;
maind[row-col+N-1] = false;
secondaryd[row+col] = false;
}
}
}

/**
* Judge if the position can lay a queen.
* @param row
* @param col
* @return
*/
private boolean canLay(int row, int col) {
// TODO Auto-generated method stub
return (!column[col] && !secondaryd[row+col] && !maind[row-col+N-1]);
}

public ArrayList<int[]> getResult() {
return result;
}
}

public class Queens {

public static void main(String[] args) {
EightQueen q = new EightQueen();
q.initQ(8); // It is a eight queens problem.
q.queens();

}

}
//Some output instances:
[0, 4, 7, 5, 2, 6, 1, 3]
[0, 5, 7, 2, 6, 3, 1, 4]
[0, 6, 3, 5, 7, 1, 4, 2]
[0, 6, 4, 7, 1, 3, 5, 2]
[1, 3, 5, 7, 2, 0, 6, 4]
[1, 4, 6, 0, 2, 7, 5, 3]
[1, 4, 6, 3, 0, 7, 5, 2]
[1, 5, 0, 6, 3, 7, 2, 4]
[1, 5, 7, 2, 0, 3, 6, 4]
[1, 6, 2, 5, 7, 4, 0, 3]
[1, 6, 4, 7, 0, 3, 5, 2]
[1, 7, 5, 0, 2, 4, 6, 3]
[2, 0, 6, 4, 7, 1, 3, 5]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: