首先,可归纳问题的条件为,n皇后之间需满足:
1.不在同一行上
2.不在同一列上
3.不在同一斜线上
4.不在同一反斜线上
输入:4
输出:第1种摆法
+ + Q +
Q + + +
+ + + Q
+ Q + +
第2种摆法
+ Q + +
+ + + Q
Q + + +
+ + Q +
4皇后问题共有2种摆法
这大段我从别人博客摘抄下来的:
这为我们提供一种遍历的思路,我们可以逐行或者逐列来进行可行摆放方案的遍历,每一行(或列)遍历出一个符合条件的位置,接着就到下一行或列遍历下一个棋子的合适位置,这种遍历思路可以保证我们遍历过程中有一个条件是绝对符合的——就是下一个棋子的摆放位置与前面的棋子不在同一行(或列)。接下来,我们只要判断当前位置是否还符合其他条件,如果符合,就遍历下一行(或列)所有位置,看看是否继续有符合条件的位置,以此类推,如果某一个行(或列)的所有位置都不合适,就返回上一行(或列)继续该行(或列)的其他位置遍历,当我们顺利遍历到最后一行(或列),且有符合条件的位置时,就是一个可行的8皇后摆放方案,累加一次八皇后可行方案的个数,然后继续遍历该行其他位置是否有合适的,如果没有,则返回上一行,遍历该行其他位置,依此下去。这样一个过程下来,我们就可以得出所有符合条件的8皇后摆放方案了。这是一个深度优先遍历的过程,同时也是经典的递归思路。
接下来,我们以逐列遍历,具体到代码,进一步说明。首先,从第一列开始找第一颗棋子的合适位置,我们知道,此时第一列的任何一个位置都是合适的,当棋子找到第一个合适的位置后,就开始到下一列考虑下一个合适的位置,此时,第二列的第一行及第二行显然就不能放第二颗棋子了,因为其与第一个棋子一个同在一行,一个同在一条斜线上。第二列第三行成为第二列第一个合适的位置,以此类推,第三列的第5行又会是一个合适位置,这个过程中,我们注意到,每一列的合适位置都是受到前面几列的位置所影响,归纳如下:
假设前面1列的棋子放在第3行,那当前列不能放的位置就一定是3行,2行,4行。因为如果放在这三行上就分别跟前一列的棋子同在一行、同在斜线、同在反斜线上,不符合我们的要求。
这是我对这段代码的解读(不一定对-_-!):
public class Main {
public static int num = 0;// 方案数
public static int maxQueen;// 皇后数;棋盘的行数、列数
public static int[] cols; // 棋盘的列
// cols[x]=y的意思是:第x列的皇后在第y行(一列只能有一个皇后)
public static void arrange(int n) {// n代表当前摆到第n列;或者可以说是摆到第n列皇后
boolean[] rows = new boolean[maxQueen];// 棋盘的行,true是不合法
for (int i = 0; i < n; i++) {// 遍历第n列之前的列
rows[cols[i]] = true;// 第i列皇后所在的那一行是不合法的
int d = n - i; // 不明白这个d代表了什么-_-!
if (cols[i] - d >= 0)// 判断是否超界
// 第i列皇后的主对角线(皇后的右下角那个格)是不合法的
rows[cols[i] - d] = true;
if (cols[i] + d <= maxQueen - 1)// 判断是否超界
// 第i列皇后的副对角(皇后的左上角那个格)线是不合法的
rows[cols[i] + d] = true;
}
for (int i = 0; i < maxQueen; i++) {
if (rows[i])// 判断当前列中的该行是否合法,true是不合法
continue;
cols[n] = i;// 当前列的皇后所在行数为i
if (n < maxQueen - 1)// 当前列不是最后一列时
arrange(n + 1);
else { // 当前列是最后一列时
num++;
print();
}
}
}// 如果当当前列中所有行都不合法时,会回溯到上一个方法
public static void print() {
System.out.println("第" + num + "种摆法");
for (int i = 0; i < maxQueen; i++) {
for (int j = 0; j < maxQueen; j++) {
if (i == cols[j])
System.out.print("Q ");// 皇后
else
System.out.print("+ ");
}
System.out.println();
}
System.out.println();
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
maxQueen = in.nextInt();
cols = new int[maxQueen];
arrange(0);
System.out.println(maxQueen + "皇后问题共有" + num + "种摆法");
}
}