实验题目 回溯法实现8皇后问题
实验要求 a.掌握递归回溯算法的基本思想。
b.学习掌握应用面向对象通用回溯程序框架解决实际问题。 提高面向对象编程的技能。
作业描述:在8*8格的棋盘上放置彼此不受攻击的8个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。8后问题等价于在n*n格的棋盘上放置8个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。
package pku.java; import java.util.ArrayList; import java.util.List; public class Main { private static int SIZE = 8; private static int TotalNumber = 0; private static List<boolean[][]> ChessBoards = new ArrayList<boolean[][]>(); public static void main(String[] args) { boolean[][] chessboard = new boolean[SIZE][SIZE]; for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { chessboard[i][j] = false; } } Main Test = new Main(); Test.put(chessboard, 0); Test.print(ChessBoards.get((int) (Math.random() * 1000) % ChessBoards.size())); System.out.println(TotalNumber); } public void print(boolean[][] chessboard) { for (int i = 0; i < SIZE; i++) { for (int k = 0; k < SIZE; k++) { if (chessboard[i][k] == true) System.out.print("# "); if (chessboard[i][k] == false) System.out.print(". "); } System.out.println(); } } public void put(boolean[][] chessboard, int level) { // 放皇后 if (level == SIZE - 1) { for (int j = 0; j < SIZE; j++) { chessboard[level][j] = true; if (safeJudge(chessboard, level, j)) { // 放最后一个皇后 boolean[][] temp = new boolean[SIZE][SIZE]; for (int i = 0; i < SIZE; i++) { for (int k = 0; k < SIZE; k++) { temp[i][k] = chessboard[i][k]; } } ChessBoards.add(temp); TotalNumber++; } chessboard[level][j] = false; } } else { for (int j = 0; j < SIZE; j++) { chessboard[level][j] = true; if (safeJudge(chessboard, level, j)) { put(chessboard, level + 1); } chessboard[level][j] = false; } } } public boolean safeJudge(boolean[][] chessboard, int x, int y) { // 放皇后时,判断放下是否安全,因为是逐行放,水平方向不会冲突 // int x_count = 0; int y_count = 0; // x-direction // for (int j = 0; j < SIZE; j++) { // if (chessboard[x][j] == true) { // ++x_count; // } // if (x_count > 1) // return false; // } // y-direction for (int i = 0; i < SIZE; i++) { if (chessboard[i][y] == true) { ++y_count; } if (y_count > 1) return false; } // oblique-direction // 主对角线 int z_count = 0; for (int i = x, j = y; i >= 0 && j >= 0; --i, --j) { if (chessboard[i][j] == true) ++z_count; if (z_count > 1) return false; } z_count = 0; for (int i = x, j = y; i < SIZE && j < SIZE; ++i, ++j) { if (chessboard[i][j] == true) ++z_count; if (z_count > 1) return false; } // 副对角线 int w_count = 0; for (int i = x, j = y; i >= 0 && j < SIZE; --i, ++j) { if (chessboard[i][j] == true) ++w_count; if (w_count > 1) return false; } w_count = 0; for (int i = x, j = y; i < SIZE && j >= 0; ++i, --j) { if (chessboard[i][j] == true) ++w_count; if (w_count > 1) return false; } return true; } }