一、问题描述
N皇后问题,就是把N个皇后放到NXN的棋盘上,使她们不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
二、问题分析
典型的回溯问题;
queens[k]表示皇后k放在queens[k]位置上。
三、算法代码
1、参数int [] queens可以是任意长度,它们的长度即代表queens.length皇后问题,可以解决任意NXN问题,当N较大时,求解时间较长;
2、参数int [] queens所有元素需要初始化为-1;
3、只能找到一个可行解。
/**
* int [] queens表示N个皇后的初始放置位置
* queens[k]表示皇后k放在queens[k]位置上
* 每个皇后可放置在0~queens.length-1的位置上
* */
public static int [] NQueens(int [] queens){
int n = queens.length;
int k = 0;
while(k >= 0){
queens[k]++;//尝试皇后K的下一个位置
//检测皇后K的当前位置是否合理(取值范围0~n-1),合适(不会发生冲突)
while(queens[k] < n && isConflict(queens, k)){
queens[k]++;
}
//检测是否找到了一个全局可行解,需要检测两个条件
if(queens[k] < n && k == n - 1){
return queens;
}
//if条件成立说明找到的只是一个局部解,继续放置下一个k+1皇后
if(queens[k] < n && k < n){
k++;
}else{//若if条件不成立则说明k皇后位置已经尝试了可放置的所有位置都不可行,执行回溯
queens[k] = -1;
k--;
}
}
return queens;
}
/**
* 当前k皇后是否会和前k - 1皇后冲突
* */
public static boolean isConflict(int [] queens, int k){
for(int i = 0; i < k; i++){
//判断是否在同一列或正负对角线上
if(queens[i] == queens[k] || Math.abs(queens[i] - queens[k]) == Math.abs(i - k)){
return true;
}
}
return false;
}
四、完整测试代码
public class NQueen {
public static void main(String[] args) {
int [] queens = new int[]{-1,-1,-1,-1};//长度可以任意指定
queens = NQueens(queens);//开始求解N皇后问题
printResult(queens);//打印出求解结果
}
/**
* int [] queens表示N个皇后的初始放置位置
* queens[k]表示皇后k放在queens[k]位置上
* 每个皇后可放置在0~queens.length-1的位置上
* */
public static int [] NQueens(int [] queens){
int n = queens.length;
int k = 0;
while(k >= 0){
queens[k]++;//尝试皇后K的下一个位置
//检测皇后K的当前位置是否合理(取值范围0~n-1),合适(不会发生冲突)
while(queens[k] < n && isConflict(queens, k)){
queens[k]++;
}
//检测是否找到了一个全局可行解,需要检测两个条件
if(queens[k] < n && k == n - 1){
return queens;
}
//if条件成立说明找到的只是一个局部解,继续放置下一个k+1皇后
if(queens[k] < n && k < n){
k++;
}else{//若if条件不成立则说明k皇后位置已经尝试了可放置的所有位置都不可行,执行回溯
queens[k] = -1;
k--;
}
}
return queens;
}
/**
* 当前k皇后是否会和前k - 1皇后冲突
* */
public static boolean isConflict(int [] queens, int k){
for(int i = 0; i < k; i++){
//判断是否在同一列或正负对角线上
if(queens[i] == queens[k] || Math.abs(queens[i] - queens[k]) == Math.abs(i - k)){
return true;
}
}
return false;
}
/**
* 打印出所有皇后位置
* */
public static void printResult(int [] queens){
int len = queens.length;
for(int i = 0; i <= len - 1; i++){
for(int j = 0; j <= len - 1; j++){
if(j == queens[i]){
System.out.print("Q" + " ");
}else{
System.out.print("X" + " ");
}
if(j == len - 1){
System.out.println();
}
}
}
}
}
五、执行结果
当queens长度为4时:
X Q X X
X X X Q
Q X X X
X X Q X
当queens长度为5时:
Q X X X X
X X Q X X
X X X X Q
X Q X X X
X X X Q X
当queens长度为10时:
Q X X X X X X X X X
X X Q X X X X X X X
X X X X X Q X X X X
X X X X X X X Q X X
X X X X X X X X X Q
X X X X Q X X X X X
X X X X X X X X Q X
X Q X X X X X X X X
X X X Q X X X X X X
X X X X X X Q X X X