八皇后问题简介:八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯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错误,至今没有查出错误原因,如有读者看出,请不吝赐教
来源:https://www.cnblogs.com/lqminn/archive/2012/08/08/2628860.html