一、实验目的及要求
实验目的
(1)掌握回溯算法的设计思想;
(2)掌握解空间树的动态生成过程。
实验要求
(1)设计解空间树的动态生成算法,并设计剪枝函数加快搜索速度;
(2)将上面图例(四皇后问题)按回溯算法搜索并输出全部的解。
二、实验环境
windows11,IDEA
三、实验内容
使用回溯算法求解N皇后问题。
问题描述:八皇后问题是十九世纪著名的数学家高斯于1850年提出的。问题是:在8×8的棋盘上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。可以把八皇后问题扩展到n皇后问题,即在n×n的棋盘上摆放n个皇后,使任意两个皇后都不能处于同一行、同一列或同一斜线上。
显然,棋盘的每一行上可以而且必须摆放一个皇后,所以,n皇后问题的可能解用一个n元向量X=(x1, x2, …, xn)表示,其中,1≤i≤n并且1≤xi≤n,即第i个皇后放在第i行第xi列上。
由于两个皇后不能位于同一列上,所以,解向量X必须满足约束条件:
xi≠xj
若两个皇后摆放的位置分别是(i, xi)和(j, xj),在棋盘上斜率为-1的斜线上,满足条件i-j= xi-xj,在棋盘上斜率为1的斜线上,满足条件i+j= xi+xj,综合两种情况,由于两个皇后不能位于同一斜线上,所以,解向量X必须满足约束条件:
|i-xi|≠|j-xj|
四皇后问题示例:
四、代码实现
public class TestHS {
int n; // 皇后个数
int x[]; // 当前解
int sum; // 当前已找到的可行方案数
static int nQueen() {
TestHS X = new TestHS();
X.n = 4;
X.sum = 0;
int[] p = new int[5];
for (int i = 0; i <= 4; i++) {
p[i] = 0;
}
X.x = p;
X.Backtrack(1);
return X.sum;
}
void Backtrack(int t) {
// t拓展的是行
if (t > n) {
sum++;
for (int i = 1; i <= n; i++) {
System.out.print(x[i] + " ");
}
System.out.println();
} else {
// 探索第t行的每一列是否有元素满足要求
for (int i = 1; i <= n; i++) {
x[t] = i;
if (Place(t)) {
Backtrack(t + 1);
}
}
}
}
boolean Place(int k) {
for (int j = 1; j < k; j++) {
if ((Math.abs(k - j) == Math.abs(x[j] - x[k])) || (x[j] == x[k])) {
return false;
}
}
return true;
}
public static void main(String[] args) {
int n = 4, m;
m = nQueen();
}
}
五、实验结果