ACWing-n皇后问题

253 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

皇后问题是指将 n 个皇后放在 n×n, 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。

1_597ec77c49-8-queens.png

现在给定整数 n,请你输出所有的满足条件的棋子摆法。

输入格式

共一行,包含整数 n

输出格式

每个解决方案占 n 行,每行输出一个长度为 n,其中 . 表示某一个位置的方格状态为空,Q 表示某一个位置的方格上摆着皇后。每个方案输出完成后,输出一个空行。

**注意:行末不能有多余空格。**输出方案的顺序任意,只要不重复且没有遗漏即可。

数据范围

1≤n≤9

输入样例:

4

输出样例:

.Q..
...Q
Q...
..Q.

..Q.
Q...
...Q
.Q..

二、思路分析:

  1. 这一道题是经典的皇后问题,我们有很多方法可以来解决这个问题,比如:DFS又或者冲突 >检测法。我们先借这一题来熟悉DFS的运用。

    我们之前做过一个数的全排列问题,其实皇后问题和全排列问题是有相同的特性的,我们可以把分别把n皇后的位置来拿出 __ __ __ __ ..... ,我们把每个皇后所在行数填上, 1 x x x ..... ,当填完以后在把符合条件的情况输出。最大的区别就是剪枝的问题,n皇后的剪枝条件为任意两个皇后都不能处于同一行、同一列或同一斜线上,所以我们要对比列上对角线上反对角线上是否已经存在皇后

  2. 我们在这一题最重要的就是回溯、剪枝的考虑

    /**剪枝条件*/ 
    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的回溯和剪枝。