八皇后问题是回溯算法中比较经典的案例。在 n × n 的棋盘中放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行、同一列、同一斜线上的棋子。
关于该题的解向量,我们可以用n元组x[1:n] 表示n后问题的解。其中,x[i] 表示皇后i放在棋盘的第i行的第x[i]列。例如说8皇后问题其中一个解可以表示如下,其中Q表示皇后所在的位置。
这里n 元组 x =[8,3,1,6,2,5,7,4],其对应的解是在棋盘的1,2,3….8行中,分别将皇后放在第8,3….4列上。
看到解向量后,我们很容易知道其解空间的结构是一个满n叉树。确定了解空间后,我们还需要将题目中给定的条件 “皇后不在同一行,同一列,同一斜线上” 转换为显示约束,从而在遍历解空间时可以裁剪掉无效的树节点。
我们取两个皇后所在位置的分别为 Q1 (i,x[i]) ,Q2 (j,x[j]), 那么不在同一行上的约束条件为i≠j,这点在定义解向量时已经进行了限定,可以不用考虑;不在同一列的约束条件为 x[i] ≠ x[j];而不在同一条斜线上的约束条件,如果把棋盘中心作为坐标原点,斜线上棋盘点构成的图形分别斜率为+1和-1的斜线,对应的图形函数分别是y=x+a,和y=-x+b,则约束条件可由下列公式推得
那么,根据上述约束条件和解向量的结构,我们可以写出一个剪枝函数来判断当前节点上得到的解是否满足约束条件,如果满足则继续搜索子树,否则剪去不可行的子树。
private boolean place(int k){
boolean placed = true;
for (int j = 1;j<k;j++){