八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。现代教学中,把八皇后问题当成一个经典递归算法例题。
下面我用递归和循环两种方式来加以描述。
1.循环方式:
package EightQueens; public class EightQueensNotRecursive { private static final boolean AVAILABLE = true; private int squares = 8, norm = squares – 1; private int positionInRow[] = new int[squares]; private int p=-1; private boolean[] rows = new boolean[squares]; private boolean[] column = new boolean[squares]; private boolean[] leftDiagonal = new boolean[2 * squares – 1]; private boolean[] rightDiagonal = new boolean[2 * squares – 1]; private static int howMany = 0; public EightQueensNotRecursive() { // To complete the initialization work for the // column,leftDiagonal,rigthDiagonal. for (int i = 0; i < squares; i++) { rows[i] = AVAILABLE; column[i] = AVAILABLE; positionInRow[i] = -1; } for (int i = 0; i < 2 * squares – 1; i++) { leftDiagonal[i] = AVAILABLE; rightDiagonal[i] = AVAILABLE; } } public void printResults(int[] columns) { int row, col; System.out.println(“八皇后问题的第 ” + howMany + ” 种解法”); System.out.print(“八皇后问题的结果为:”); for (int e : columns) { System.out.print(e); } System.out.println(“\n具体的图示如下图所示:”); for (row = 0; row < squares; row++) { for (col = 0; col < squares; col++) { if (col == positionInRow[row]) { System.out.print(“@”); } else { System.out.print(“*”); } } System.out.println(); } System.out.println(); } public void putQueen() { int row=0, col; while (true) { for (col = p + 1; col < squares; col++) { if(rows[row]==AVAILABLE&&column[col]==AVAILABLE&&leftDiagonal[row+col]==AVAILABLE&&rightDiagonal[row-col+norm]==AVAILABLE) { break; } } //在当前的行里面找到了可以放置皇后的位置 if(col<squares) { rows[row]=!AVAILABLE; column[col]=!AVAILABLE; leftDiagonal[row+col]=!AVAILABLE; rightDiagonal[row-col+norm]=!AVAILABLE; positionInRow[row]=col; p=col; }else//如果当前行没办反放置皇后了,那么回溯 { if(row>0)//到前一行 { row–; p=positionInRow[row]; rows[row]=AVAILABLE; column[p]=AVAILABLE; leftDiagonal[row+p]=AVAILABLE; rightDiagonal[row-p+norm]=AVAILABLE; positionInRow[row]=-1; continue; }else { break; } } if(row==squares-1) { howMany+=1; printResults(positionInRow); p=positionInRow[row]; rows[row]=AVAILABLE; column[p]=AVAILABLE; leftDiagonal[row+p]=AVAILABLE; rightDiagonal[row-p+norm]=AVAILABLE; positionInRow[row]=-1; continue; } else { row++; p=-1; continue; } } } public static void main(String args[]) { EightQueensNotRecursive eightQueens=new EightQueensNotRecursive(); eightQueens.putQueen(); System.out.println(“皇后问题一共有”+howMany+”种解法”); } } 2.递归方式: package EightQueens; public class EightQueensRecursive { private static final boolean AVAILABLE=true; private int squares=8,norm=squares-1; private int positionInRow[]=new int[squares]; private boolean[] column=new boolean[squares]; private boolean[] leftDiagonal=new boolean[2*squares-1]; private boolean[] rightDiagonal=new boolean[2*squares-1]; private static int howMany=0; public EightQueensRecursive(){ //To complete the initialization work for the column,leftDiagonal,rigthDiagonal. for(int i=0;i<squares;i++){ column[i]=AVAILABLE; positionInRow[i]=-1; } for(int i=0;i<2*squares-1;i++){ leftDiagonal[i]=AVAILABLE; rightDiagonal[i]=AVAILABLE; } } public void printResults(int[] columns){ int row,col; System.out.println(“八皇后问题的第 “+howMany+” 种解法”); System.out.print(“八皇后问题的结果为:”); for(int e:columns){ System.out.print(e); } System.out.println(“\n具体的图示如下图所示:”); for(row=0;row<squares;row++){ for(col=0;col<squares;col++){ if(col==positionInRow[row]){ System.out.print(“@”); }else{ System.out.print(“*”); } } System.out.println(); } System.out.println(); } public void putQueen(int row){ //如果前面已经得到了一个可行解 for(int i=0;i<squares;i++) { if(row>squares-1) break; if(column[i]==AVAILABLE&&leftDiagonal[row+i]==AVAILABLE&&rightDiagonal[row-i+norm]==AVAILABLE) { positionInRow[row]=i; column[i]=!AVAILABLE; leftDiagonal[row+i]=!AVAILABLE; rightDiagonal[row-i+norm]=!AVAILABLE; if(row<squares-1){ putQueen(row+1); }else { howMany+=1; printResults(positionInRow); } column[i]=AVAILABLE; leftDiagonal[row+i]=AVAILABLE; rightDiagonal[row-i+norm]=AVAILABLE; } } } public static void main(String args[]){ EightQueensRecursive eightQueens=new EightQueensRecursive(); eightQueens.putQueen(0); System.out.println(“皇后问题一共找到了 “+howMany+”组解。”); } }