一.八皇后问题描述
八皇后问题(英文:Eight queens),是由国际象棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。
问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
二.解决思路
1.利用数组来描述八皇后问题
为了方便表达,可以用一个8*8的二数组来代表棋盘,然而实际上只需要也只能够摆放八个棋子,所以也可以用一个容量为8的一维数组来表示每一行的第几列用来摆放皇后。
例如arr[] ={0,4,7,5,2,6,1,3}则表示分别在第一行的第一列,第二行的第五列摆放皇后等等,即
queen | |||||||
queen | |||||||
queen | |||||||
queen | |||||||
queen | |||||||
queen | |||||||
queen | |||||||
queen |
2.定义摆放的规则
可以定义一个isright函数来判断摆放的位置是否正确
private boolean isright(int n){//n表示传入的是第几行的皇后
boolean isright=true;
for(int i=0;i<n;i++){
if(arr[i]==arr[n]||Math.abs(n-i)==Math.abs(arr[n]-arr[i])){//斜率为正负一,或者在同一列
isright= false;
break;
}
}
return isright;
}
3.如何摆放
定义一个add函数,利用递归的原理一行一行的摆放
private void add(int n){//n表示放的是哪一列
if(n==max){//全部摆放完毕
printq();//输出摆放结果
return;
}
for(int i=0;i<max;i++){
//从第0列开始,一列一列的试放
arr[n]=i;
if(isright(n)){
//利用isright方法,检验摆放的位置是否正确,如果正确,则继续摆放下一行
add(n+1);
}
}
}
最后,只需要再定义一个输出摆放结果的方法即可
private void printq(){
count++;//用来记录输出了多少次结果,即有多少个正确方案
for (int element : arr) {
System.out.printf(element+" ");
}
System.out.println();
}
三.总结
解决该问题利用递归的思想,一个一个试错来得到最后的结果
//八皇后问题
public class Queen8 {
int max=8;
int arr[]=new int[max];
static int count;
public static void main(String[] args) {
Queen8 solution=new Queen8();
solution.add(0);
System.out.println("总共有"+count+"种方法");
}
//放置第n行皇后
private void add(int n){
if(n==max){
printq();
return;
}
for(int i=0;i<max;i++){
arr[n]=i;
if(isright(n)){
add(n+1);
}
}
}
//检测该皇后是否和前面已经摆放的皇后冲突
private boolean isright(int n){
boolean isright=true;
for(int i=0;i<n;i++){
if(arr[i]==arr[n]||Math.abs(n-i)==Math.abs(arr[n]-arr[i])){
isright= false;
break;
}
}
return isright;
}
//输出皇后摆放位置
private void printq(){
count++;
for (int element : arr) {
System.out.printf(element+" ");
}
System.out.println();
}
}