问题: 设计一种算法,打印 N 皇后在 N × N 棋盘上的各种摆法,其中每个皇后都不同行、不同列,也不在对角线上。这里的“对角线”指的是所有的对角线,不只是平分整个棋盘的那两条对角线。
阶梯思路:回溯法,先在第一行的第一个位置放置一个皇后,发现可以放下,于是找到第二行的第一个位置,发现不能放下,于是换下一个位置,第二行的第二个位置,发现可以放下,于是找第三行的第一个位置,不能放下,第三行的第二个位置也不能放下,可以发现规律,要想放下所在行的的第n个位置,需要和前面的n-1行的位置去竞争,如果发现冲突则不能放下,问题的回溯点(如果遍历了前面n-1行已经放下的皇后和要放下的皇后冲突则继续需要第n行的下一个位置,坐标中两个点的位置有冲突的规律是,横坐标和纵坐标的差的绝对值不想等则不冲突)
public class Queen {
private int sum = 0;
//八皇后问题设置数组大小为8;
// 解释数组的含义(每一个数组代表一种解法)
// :数组下标i表示第i+1行,值res[i]为第i+1行的第res[i]的位置有皇后;
private int [] res = new int[8] ;
private int max = 8;
private int time = 0;
private boolean check(int row) {
time++;
for (int i = 0; i < row; i++) {
/**
* 判断当前位置放入皇后是否会满足规则
* 判读两个坐标位置的皇后是否会相互影响的规则:
* 横坐标和纵坐标的差的绝对值相等则影响,否则则互不影响
* (转换为当前解法的规定就是res的下标差和值的差是否相等)
*/
if (res[i] == res[row] || Math.abs(row - i) == Math.abs(res[row] - res[i])) {
return false;
}
}
return true;
}
public void findRes(int row) {
if (row > 7) {
sum ++;
printRes();
//递归出口
return;
}
for (int i = 0; i < max; i++) {
res[row] = i;
if(check(row)) {
findRes(row +1);
}
}
}
//每一个数组代表一种解法,数组解释建属性注解
public void printRes() {
for (int i = 0, length = res.length; i < length; i++) {
System.out.print(res[i] + " ");
}
System.out.println();
}
public static void main (String[] args) {
Queen queen = new Queen();
queen.setMax(8);
queen.findRes(0);
System.out.printf("八皇后问题的解法一共有%d", queen.sum);
System.out.printf("一共进行了%d次运算", queen.time);
}
}
暂时定为每周更新四次,明天预告:求二叉树两个节点的共同节点