八皇后问题简介:八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。
解决方法:回溯算法
Java代码:
public class QueenPosition {
private int x;
private int y;
public QueenPosition(int row, int column){
x = row;
y = column;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
这个类是用来存储皇后放置在棋盘上的位置的。
以下这个类是解法:
import java.util.ArrayList;
public class EightQueens {
static ArrayList<QueenPosition> path = new ArrayList<QueenPosition>();
static int pathCount = 0;//第几种解法,用于打印消息
public static void main(String[] args) {
// TODO Auto-generated method stub
findQueenSolution(0, 0, path);//表明初始化的位置,第一个和第二个参数表明从(0,0)坐标处开始放置,之所以这么写,原因见后面,先放着。path是用来记录路径的
}
//问题核心
public static void findQueenSolution(int xStart, int yStart, ArrayList<QueenPosition> path){
for(int row = xStart; row < 8 ; row++){//每一行放置一个
//以下这个判断是为了在回溯过程中,只影响回溯行,而不影响接下去的行
if(row > xStart){
yStart = 0;
}
//表明是否找到
boolean isFound = false;
for(int column = yStart; column < 8 && !isFound; column ++){
//遍历每一列
if(isLegal(row, column, path)){
//如果是合法的(表明可以放置),加入路径
path.add(new QueenPosition(row,column));
isFound = true;//表明找到了!
if(row == 7){
//说明是最后一行,此时是可以打印的,同时最后一行也需要回溯,因为可能有多个届
pathCount++;
printPath(path);
reCall(path);
}
}else{
//非法情况下
if(column == 7){
//说明是最后一列,此时需要回溯,也就是说上一行摆的位置不对
reCall(path);
}
}
}
}
}
//回溯(为了更加清楚的知道这个方法的原理,举一个例子:假设前面四行全部已经放置好皇后,在放置第五行的时候,如果column从0遍历到7都是非法的,那么很明显,此时需要回溯,将第四行从路径中删除,假设第四行原先皇后的摆放位置是(3,4),那么为了不重复放置在此处,需要从(3,5)开始往右边遍历,这也就是为什么需要使用++orginColumn做参数的原因;但是还有可能出现一种情况就是第四行原先的摆放位置是(3,7),此时第四行也不能进行回溯,由此必须也要把它给删掉,回溯到第三行,此时不必担心第一行和第二行,因为这样不符合八皇后的放置规则)
public static void reCall(ArrayList<QueenPosition> path){
int pathLength = path.size();
if(pathLength > 0){
//如果还可以回溯(如果已经在第一行,则没办法再去回溯)
int orginColumn = path.get(pathLength-1).getY();
path.remove(pathLength-1);//把最后一个除掉
int row = pathLength-1;
if(orginColumn == 7 && pathLength > 1){//此时表明上一行也无法回溯
orginColumn = path.get(pathLength-2).getY();
path.remove(pathLength-2);
--row;
}
findQueenSolution(row, ++orginColumn, copyPath(path));//回溯
}
}
public static boolean isLegal(int x, int y, ArrayList<QueenPosition> path){//检测放置位置是否合法
boolean legal = true;
int pathLength = path.size();
for(int index = 0; index < pathLength; index ++){
int xCor = path.get(index).getX();
int yCor = path.get(index).getY();
int xDiff = Math.abs(xCor - x);
int yDiff = Math.abs(yCor - y);
if((xDiff == yDiff) || xDiff == 0 || yDiff == 0){
//相等表明在对角线上,等于0表明在同一行或者同一列中
legal = false;
break;
}
}
return legal;
}
//打印函数
public static void printPath(ArrayList<QueenPosition> path){
System.out.print("第 " + pathCount + "种解法:");
for(int position = 0; position < path.size(); position ++){
System.out.print("(" + path.get(position).getX() + " , " + path.get(position).getY() + ") ");
}
System.out.println();
}
//复制arrayList,避免同时操作一个arrayList
public static ArrayList<QueenPosition> copyPath(ArrayList<QueenPosition> orginPath){
ArrayList<QueenPosition> copyList = new ArrayList<QueenPosition>();
for(int index = 0; index < orginPath.size(); index ++){
copyList.add(orginPath.get(index));
}
return copyList;
}
}
打印的结果:
第 1种解法:(0 , 0) (1 , 4) (2 , 7) (3 , 5) (4 , 2) (5 , 6) (6 , 1) (7 , 3)
第 2种解法:(0 , 0) (1 , 5) (2 , 7) (3 , 2) (4 , 6) (5 , 3) (6 , 1) (7 , 4)
第 3种解法:(0 , 0) (1 , 6) (2 , 3) (3 , 5) (4 , 7) (5 , 1) (6 , 4) (7 , 2)
第 4种解法:(0 , 0) (1 , 6) (2 , 4) (3 , 7) (4 , 1) (5 , 3) (6 , 5) (7 , 2)
第 5种解法:(0 , 1) (1 , 3) (2 , 5) (3 , 7) (4 , 2) (5 , 0) (6 , 6) (7 , 4)
第 6种解法:(0 , 1) (1 , 4) (2 , 6) (3 , 0) (4 , 2) (5 , 7) (6 , 5) (7 , 3)
第 7种解法:(0 , 1) (1 , 4) (2 , 6) (3 , 3) (4 , 0) (5 , 7) (6 , 5) (7 , 2)
第 8种解法:(0 , 1) (1 , 5) (2 , 0) (3 , 6) (4 , 3) (5 , 7) (6 , 2) (7 , 4)
第 9种解法:(0 , 1) (1 , 5) (2 , 7) (3 , 2) (4 , 0) (5 , 3) (6 , 6) (7 , 4)
第 10种解法:(0 , 1) (1 , 6) (2 , 2) (3 , 5) (4 , 7) (5 , 4) (6 , 0) (7 , 3)
第 11种解法:(0 , 1) (1 , 6) (2 , 4) (3 , 7) (4 , 0) (5 , 3) (6 , 5) (7 , 2)
第 12种解法:(0 , 1) (1 , 7) (2 , 5) (3 , 0) (4 , 2) (5 , 4) (6 , 6) (7 , 3)
第 13种解法:(0 , 2) (1 , 0) (2 , 6) (3 , 4) (4 , 7) (5 , 1) (6 , 3) (7 , 5)
第 14种解法:(0 , 2) (1 , 4) (2 , 1) (3 , 7) (4 , 0) (5 , 6) (6 , 3) (7 , 5)
第 15种解法:(0 , 2) (1 , 4) (2 , 1) (3 , 7) (4 , 5) (5 , 3) (6 , 6) (7 , 0)
第 16种解法:(0 , 2) (1 , 4) (2 , 6) (3 , 0) (4 , 3) (5 , 1) (6 , 7) (7 , 5)
第 17种解法:(0 , 2) (1 , 4) (2 , 7) (3 , 3) (4 , 0) (5 , 6) (6 , 1) (7 , 5)
第 18种解法:(0 , 2) (1 , 5) (2 , 1) (3 , 4) (4 , 7) (5 , 0) (6 , 6) (7 , 3)
第 19种解法:(0 , 2) (1 , 5) (2 , 1) (3 , 6) (4 , 0) (5 , 3) (6 , 7) (7 , 4)
第 20种解法:(0 , 2) (1 , 5) (2 , 1) (3 , 6) (4 , 4) (5 , 0) (6 , 7) (7 , 3)
第 21种解法:(0 , 2) (1 , 5) (2 , 3) (3 , 0) (4 , 7) (5 , 4) (6 , 6) (7 , 1)
第 22种解法:(0 , 2) (1 , 5) (2 , 3) (3 , 1) (4 , 7) (5 , 4) (6 , 6) (7 , 0)
第 23种解法:(0 , 2) (1 , 5) (2 , 7) (3 , 0) (4 , 3) (5 , 6) (6 , 4) (7 , 1)
第 24种解法:(0 , 2) (1 , 5) (2 , 7) (3 , 0) (4 , 4) (5 , 6) (6 , 1) (7 , 3)
第 25种解法:(0 , 2) (1 , 5) (2 , 7) (3 , 1) (4 , 3) (5 , 0) (6 , 6) (7 , 4)
第 26种解法:(0 , 2) (1 , 6) (2 , 1) (3 , 7) (4 , 4) (5 , 0) (6 , 3) (7 , 5)
第 27种解法:(0 , 2) (1 , 6) (2 , 1) (3 , 7) (4 , 5) (5 , 3) (6 , 0) (7 , 4)
第 28种解法:(0 , 2) (1 , 7) (2 , 3) (3 , 6) (4 , 0) (5 , 5) (6 , 1) (7 , 4)
第 29种解法:(0 , 3) (1 , 0) (2 , 4) (3 , 7) (4 , 1) (5 , 6) (6 , 2) (7 , 5)
第 30种解法:(0 , 3) (1 , 0) (2 , 4) (3 , 7) (4 , 5) (5 , 2) (6 , 6) (7 , 1)
第 31种解法:(0 , 3) (1 , 1) (2 , 4) (3 , 7) (4 , 5) (5 , 0) (6 , 2) (7 , 6)
第 32种解法:(0 , 3) (1 , 1) (2 , 6) (3 , 2) (4 , 5) (5 , 7) (6 , 0) (7 , 4)
第 33种解法:(0 , 3) (1 , 1) (2 , 6) (3 , 2) (4 , 5) (5 , 7) (6 , 4) (7 , 0)
第 34种解法:(0 , 3) (1 , 1) (2 , 6) (3 , 4) (4 , 0) (5 , 7) (6 , 5) (7 , 2)
第 35种解法:(0 , 3) (1 , 1) (2 , 7) (3 , 4) (4 , 6) (5 , 0) (6 , 2) (7 , 5)
第 36种解法:(0 , 3) (1 , 1) (2 , 7) (3 , 5) (4 , 0) (5 , 2) (6 , 4) (7 , 6)
第 37种解法:(0 , 3) (1 , 5) (2 , 0) (3 , 4) (4 , 1) (5 , 7) (6 , 2) (7 , 6)
第 38种解法:(0 , 3) (1 , 5) (2 , 7) (3 , 1) (4 , 6) (5 , 0) (6 , 2) (7 , 4)
第 39种解法:(0 , 3) (1 , 5) (2 , 7) (3 , 2) (4 , 0) (5 , 6) (6 , 4) (7 , 1)
第 40种解法:(0 , 3) (1 , 6) (2 , 0) (3 , 7) (4 , 4) (5 , 1) (6 , 5) (7 , 2)
第 41种解法:(0 , 3) (1 , 6) (2 , 2) (3 , 7) (4 , 1) (5 , 4) (6 , 0) (7 , 5)
第 42种解法:(0 , 3) (1 , 6) (2 , 4) (3 , 1) (4 , 5) (5 , 0) (6 , 2) (7 , 7)
第 43种解法:(0 , 3) (1 , 6) (2 , 4) (3 , 2) (4 , 0) (5 , 5) (6 , 7) (7 , 1)
第 44种解法:(0 , 3) (1 , 7) (2 , 0) (3 , 2) (4 , 5) (5 , 1) (6 , 6) (7 , 4)
第 45种解法:(0 , 3) (1 , 7) (2 , 0) (3 , 4) (4 , 6) (5 , 1) (6 , 5) (7 , 2)
第 46种解法:(0 , 3) (1 , 7) (2 , 4) (3 , 2) (4 , 0) (5 , 6) (6 , 1) (7 , 5)
第 47种解法:(0 , 4) (1 , 0) (2 , 3) (3 , 5) (4 , 7) (5 , 1) (6 , 6) (7 , 2)
第 48种解法:(0 , 4) (1 , 0) (2 , 7) (3 , 3) (4 , 1) (5 , 6) (6 , 2) (7 , 5)
第 49种解法:(0 , 4) (1 , 0) (2 , 7) (3 , 5) (4 , 2) (5 , 6) (6 , 1) (7 , 3)
第 50种解法:(0 , 4) (1 , 1) (2 , 3) (3 , 5) (4 , 7) (5 , 2) (6 , 0) (7 , 6)
第 51种解法:(0 , 4) (1 , 1) (2 , 3) (3 , 6) (4 , 2) (5 , 7) (6 , 5) (7 , 0)
第 52种解法:(0 , 4) (1 , 1) (2 , 5) (3 , 0) (4 , 6) (5 , 3) (6 , 7) (7 , 2)
第 53种解法:(0 , 4) (1 , 1) (2 , 7) (3 , 0) (4 , 3) (5 , 6) (6 , 2) (7 , 5)
第 54种解法:(0 , 4) (1 , 2) (2 , 0) (3 , 5) (4 , 7) (5 , 1) (6 , 3) (7 , 6)
第 55种解法:(0 , 4) (1 , 2) (2 , 0) (3 , 6) (4 , 1) (5 , 7) (6 , 5) (7 , 3)
第 56种解法:(0 , 4) (1 , 2) (2 , 7) (3 , 3) (4 , 6) (5 , 0) (6 , 5) (7 , 1)
第 57种解法:(0 , 4) (1 , 6) (2 , 0) (3 , 2) (4 , 7) (5 , 5) (6 , 3) (7 , 1)
第 58种解法:(0 , 4) (1 , 6) (2 , 0) (3 , 3) (4 , 1) (5 , 7) (6 , 5) (7 , 2)
第 59种解法:(0 , 4) (1 , 6) (2 , 1) (3 , 3) (4 , 7) (5 , 0) (6 , 2) (7 , 5)
第 60种解法:(0 , 4) (1 , 6) (2 , 1) (3 , 5) (4 , 2) (5 , 0) (6 , 3) (7 , 7)
第 61种解法:(0 , 4) (1 , 6) (2 , 1) (3 , 5) (4 , 2) (5 , 0) (6 , 7) (7 , 3)
第 62种解法:(0 , 4) (1 , 6) (2 , 3) (3 , 0) (4 , 2) (5 , 7) (6 , 5) (7 , 1)
第 63种解法:(0 , 4) (1 , 7) (2 , 3) (3 , 0) (4 , 2) (5 , 5) (6 , 1) (7 , 6)
第 64种解法:(0 , 4) (1 , 7) (2 , 3) (3 , 0) (4 , 6) (5 , 1) (6 , 5) (7 , 2)
第 65种解法:(0 , 5) (1 , 0) (2 , 4) (3 , 1) (4 , 7) (5 , 2) (6 , 6) (7 , 3)
第 66种解法:(0 , 5) (1 , 1) (2 , 6) (3 , 0) (4 , 2) (5 , 4) (6 , 7) (7 , 3)
第 67种解法:(0 , 5) (1 , 1) (2 , 6) (3 , 0) (4 , 3) (5 , 7) (6 , 4) (7 , 2)
第 68种解法:(0 , 5) (1 , 2) (2 , 0) (3 , 6) (4 , 4) (5 , 7) (6 , 1) (7 , 3)
第 69种解法:(0 , 5) (1 , 2) (2 , 0) (3 , 7) (4 , 3) (5 , 1) (6 , 6) (7 , 4)
第 70种解法:(0 , 5) (1 , 2) (2 , 0) (3 , 7) (4 , 4) (5 , 1) (6 , 3) (7 , 6)
第 71种解法:(0 , 5) (1 , 2) (2 , 4) (3 , 6) (4 , 0) (5 , 3) (6 , 1) (7 , 7)
第 72种解法:(0 , 5) (1 , 2) (2 , 4) (3 , 7) (4 , 0) (5 , 3) (6 , 1) (7 , 6)
第 73种解法:(0 , 5) (1 , 2) (2 , 6) (3 , 1) (4 , 3) (5 , 7) (6 , 0) (7 , 4)
第 74种解法:(0 , 5) (1 , 2) (2 , 6) (3 , 1) (4 , 7) (5 , 4) (6 , 0) (7 , 3)
第 75种解法:(0 , 5) (1 , 2) (2 , 6) (3 , 3) (4 , 0) (5 , 7) (6 , 1) (7 , 4)
第 76种解法:(0 , 5) (1 , 3) (2 , 0) (3 , 4) (4 , 7) (5 , 1) (6 , 6) (7 , 2)
第 77种解法:(0 , 5) (1 , 3) (2 , 1) (3 , 7) (4 , 4) (5 , 6) (6 , 0) (7 , 2)
第 78种解法:(0 , 5) (1 , 3) (2 , 6) (3 , 0) (4 , 2) (5 , 4) (6 , 1) (7 , 7)
第 79种解法:(0 , 5) (1 , 3) (2 , 6) (3 , 0) (4 , 7) (5 , 1) (6 , 4) (7 , 2)
第 80种解法:(0 , 5) (1 , 7) (2 , 1) (3 , 3) (4 , 0) (5 , 6) (6 , 4) (7 , 2)
第 81种解法:(0 , 6) (1 , 0) (2 , 2) (3 , 7) (4 , 5) (5 , 3) (6 , 1) (7 , 4)
第 82种解法:(0 , 6) (1 , 1) (2 , 3) (3 , 0) (4 , 7) (5 , 4) (6 , 2) (7 , 5)
第 83种解法:(0 , 6) (1 , 1) (2 , 5) (3 , 2) (4 , 0) (5 , 3) (6 , 7) (7 , 4)
第 84种解法:(0 , 6) (1 , 2) (2 , 0) (3 , 5) (4 , 7) (5 , 4) (6 , 1) (7 , 3)
第 85种解法:(0 , 6) (1 , 2) (2 , 7) (3 , 1) (4 , 4) (5 , 0) (6 , 5) (7 , 3)
第 86种解法:(0 , 6) (1 , 3) (2 , 1) (3 , 4) (4 , 7) (5 , 0) (6 , 2) (7 , 5)
第 87种解法:(0 , 6) (1 , 3) (2 , 1) (3 , 7) (4 , 5) (5 , 0) (6 , 2) (7 , 4)
第 88种解法:(0 , 6) (1 , 4) (2 , 2) (3 , 0) (4 , 5) (5 , 7) (6 , 1) (7 , 3)
第 89种解法:(0 , 7) (1 , 1) (2 , 3) (3 , 0) (4 , 6) (5 , 4) (6 , 2) (7 , 5)
第 90种解法:(0 , 7) (1 , 1) (2 , 4) (3 , 2) (4 , 0) (5 , 6) (6 , 3) (7 , 5)
第 91种解法:(0 , 7) (1 , 2) (2 , 0) (3 , 5) (4 , 1) (5 , 4) (6 , 6) (7 , 3)
第 92种解法:(0 , 7) (1 , 3) (2 , 0) (3 , 2) (4 , 5) (5 , 1) (6 , 6) (7 , 4)
备注:运行的时候,会出现第93,94,95种解,和前面的5,6,7是重复的,并且会发生StackOverflowError错误,至今没有查出错误原因,如有读者看出,请不吝赐教