Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
皇后问题是指将 n 个皇后放在 n×n, 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
现在给定整数 n,请你输出所有的满足条件的棋子摆法。
输入格式
共一行,包含整数 n。
输出格式
每个解决方案占 n 行,每行输出一个长度为 n,其中
.表示某一个位置的方格状态为空,Q表示某一个位置的方格上摆着皇后。每个方案输出完成后,输出一个空行。**注意:行末不能有多余空格。**输出方案的顺序任意,只要不重复且没有遗漏即可。
数据范围
1≤n≤9
输入样例:
4输出样例:
.Q.. ...Q Q... ..Q. ..Q. Q... ...Q .Q..
二、思路分析:
-
这一道题是经典的皇后问题,我们有很多方法可以来解决这个问题,比如:DFS又或者冲突 >检测法。我们先借这一题来熟悉DFS的运用。
我们之前做过一个数的全排列问题,其实皇后问题和全排列问题是有相同的特性的,我们可以把分别把n皇后的位置来拿出 __ __ __ __ ..... ,我们把每个皇后所在行数填上, 1 x x x ..... ,当填完以后在把符合条件的情况输出。最大的区别就是剪枝的问题,n皇后的剪枝条件为任意两个皇后都不能处于同一行、同一列或同一斜线上,所以我们要对比列上对角线上反对角线上是否已经存在皇后
-
我们在这一题最重要的就是回溯、剪枝的考虑
/**剪枝条件*/ if(!col[i]&& !dg[u + i] && !udg[n - u + i]){ /**深搜*/ g[u][i] = 'Q'; col[i] = dg[u + i] = udg[n -u + i] = true; dfs(u + 1); /**回溯*/ col[i] = dg[u + i] = udg[n -u + i] = false; g[u][i] = '.'; }
三、AC 代码:
import java.util.Scanner;
/**
* n−皇后问题是指将 n 个皇后放在 n×n 的国际象棋棋盘上,
* 使得皇后不能相互攻击到,
* 即任意两个皇后都不能处于同一行、同一列或同一斜线上。
*/
public class N_queen {
public static int n;
/** 存放棋盘 */
public static char[][] g = null;
/** col数组是列是否放过、dg数组是对角线是否放过、udg数组反对角线是否放过 */
public static boolean[] col,dg,udg = null;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
// 初始化数组
g = new char[n+1][n+1];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
g[i][j] = '.';
}
}
col = new boolean[n + 1];
dg = new boolean[2 * n - 1 + 1];
udg = new boolean[2 * n - 1 + 1];
dfs(0);
scan.close();
}
public static void dfs(int u){
if(u == n){
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(g[i][j]+"");
}
System.out.println("");
}
System.out.println("");
return;
}
for (int i = 0; i < n; i++) {
if(!col[i]&& !dg[u + i] && !udg[n - u + i]){
g[u][i] = 'Q';
col[i] = dg[u + i] = udg[n -u + i] = true;
dfs(u + 1);
col[i] = dg[u + i] = udg[n -u + i] = false;
g[u][i] = '.';
}
}
}
}
四、总结:
我们可以通过这个题目来深入的理解DFS的回溯和剪枝。