实验题目 回溯法实现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;
}
}