8皇后问题表述:在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n×n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。求不同的解的个数。
解向量:(x1, x2, … , xn)
显约束:xi = 1,2, … ,n
隐约束:
1)不同列:xi != xj
2)不处于同一正、反对角线:|i-j| != |x(i)-x(j)|
利用递归回溯和迭代回溯两种不同的方法实现:
// 皇后问题等价于求所有满足条件的子集树
class NQueueProblem {
3:
int[] yPos;
int n;
int sum;
7:
int n) {
this.n = n;
10: init(n);
11: }
12:
int n) {
int[n];
int i = 0; i < n; i++) {
16: yPos[i] = 0;
17: }
18: }
19:
// 递归回溯方法进行求解
// 将皇后置于第t行
int t) {
if (t == n) {
24: sum++;
//输出当前解
26: printSolution();
else {
int j = 0; j < n; j++) {
// 皇后放置在第t行j列
if (isPlace(t)) {
// 考虑第t+1行
32: backtrack(t + 1);
33: }
34: }
35: }
36: }
37:
// 迭代回溯实现
// 采用树的非递归深度优先遍历算法,将回溯法表示为一个非递归迭代过程
void iterativeBacktrack() {
//从第0行开始迭代
42: yPos[t] = -1;
while (t>=0) {
// 向右移一列
/* 向右移至出最右列或可以放置皇后的列 */
while ((yPos[t] <n) && !(isPlace(t))) {
47: yPos[t] += 1;
48: }
// 向右移未移出棋盘
if (yPos[t] < n)
51: {
// 已移至最后一行
if (t == n-1) {
54: sum++;
55: printSolution();
56: }
else {
/* 向下移一行 */
59: t++;
60: yPos[t] = -1;
61: }
62: }
else {
// 即yPos[t]>n, 迭代到最后一列仍无解,则回溯到前一行
65: t--;
66: }
67: }
68: }
69:
int t) {
int i = 0; i < t; i++) {
if ((Math.abs(i - t) == Math.abs(yPos[i] - yPos[t]))
73: || (yPos[i] == yPos[t])) {
return false;
75: }
76: }
return true;
78: }
79:
void printSolution() {
int i = 0; i < n; i++) {
);
if (i == n - 1) {
84: System.out.println();
85: }
86: }
87: }
88:
void main(String[] args) {
new NQueueProblem(8);
);
92: queen.backtrack(0);
);
94: queen.iterativeBacktrack();
95:
96: }
97: }