DFS学习初步二(N Queens问题)(Java实现)

先看一下N皇后问题

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

这里写图片描述

上图为 8 皇后问题的一种解法。

给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

示例:

输入: 4
输出: [
[“.Q..”, // 解法 1
“…Q”,
“Q…”,
“..Q.”],

[“..Q.”, // 解法 2
“Q…”,
“…Q”,
“.Q..”]
]
解释: 4 皇后问题存在两个不同的解法。

思路

这种类型的问题其实主要是在于对于所有情况的一次遍历比如说我们可以看图
这里写图片描述
可以看到查找可以用的有效解的过程是深度优先搜索DFS的过程,其实就是递归进行搜索的过程,需要注意的是进行递归之后,为了重复利用空间,我们需要取消先前搜索过程中的建立的标记我们将所有遍历后的结果,打印出来就是这个题目的解法了
这个题目使用C语言去解题需要使用较为频繁的指针操作所以我们使用Java来解题

重点

需要注意的是
我们需要使用程序语言来描述皇后问题的具体要求,如果说我们现在有两个皇后的坐标分别是(x,y)(i,j),比如说同一横行的两个皇后,我们使用x==i来描述,同一个主对角线的两个皇后我们使用x-y==i-j来表示,而同一副对角线的两个皇后的位置关系我们使用x+y==i+j来表示,这是筛选的必要条件也是对于八皇后问题的数学抽象

class solution {
    public List<List<String>> solveNQueens(int n) {
        char [][] board =new char[n][n];//初始化棋盘
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                board[i][j]='.';
                }
        }
        List<List<String>> res =new ArrayList<List<String>>();//创建存储结果的二二维List
        dfs(board,0,res);//启动DFS
        return res;
    }
    //先进行第一列的遍历,然后换第二列的不同行然后...
    private void dfs(char [][] board,int colIndex,List<List<String>> res){
        if(colIndex==board.length){//已经递归至最后一列
            res.add(structList(board));
            return ;
        }

        for(int i=0;i<board.length;i++){
            if(validate(board,i,colIndex)){
                board[i][colIndex]='Q';
                dfs(board,colIndex+1,res);//递归遍历
                board[i][colIndex]='.';//取消标记
            }
        }
    }
    //验证摆放棋盘的位置合法性
    private boolean validate(char [][] board,int x,int y){
        for(int i=0;i<board.length;i++){
            for(int j=0;j<y;j++){
                if(board[i][j]=='Q'&&(x+j==i+y||x+y==i+j||x==i))
                    return false;
            }
        }
        return true ;
    }
    //将遍历结果进行格式化
    private List<String> structList(char[][] board){
        List<String> res =new LinkedList<String>();
         for(int i=0;i<board.length;i++){
             String s=new String (board[i]);
             res.add(s);           
         }   
         return res;        
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
n 皇后问题是指在 n×n 的棋盘上放置 n 个皇后,使得皇后不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。这个问题可以使用回溯法进行求解。 Java 实现如下: ```java public class NQueens { private int n; private int[] queens; private boolean[] cols; private boolean[] diag1; private boolean[] diag2; private List<List<String>> res; public List<List<String>> solveNQueens(int n) { this.n = n; this.queens = new int[n]; this.cols = new boolean[n]; this.diag1 = new boolean[2 * n - 1]; this.diag2 = new boolean[2 * n - 1]; this.res = new ArrayList<>(); backtrack(0); return res; } private void backtrack(int row) { if (row == n) { res.add(generateBoard()); return; } for (int col = 0; col < n; col++) { int d1 = row + col; int d2 = row - col + n - 1; if (!cols[col] && !diag1[d1] && !diag2[d2]) { queens[row] = col; cols[col] = true; diag1[d1] = true; diag2[d2] = true; backtrack(row + 1); cols[col] = false; diag1[d1] = false; diag2[d2] = false; } } } private List<String> generateBoard() { List<String> board = new ArrayList<>(); for (int i = 0; i < n; i++) { char[] row = new char[n]; Arrays.fill(row, '.'); row[queens[i]] = 'Q'; board.add(new String(row)); } return board; } } ``` 在该代码中,我们使用了一个一维数组 queens 来表示每一行中皇后的位置,queens[i] 表示第 i 行中皇后所在的列数。同时,我们使用了三个一维数组 cols、diag1 和 diag2 分别表示每一列、每一条正斜线和每一条反斜线上是否有皇后。 在回溯函数 backtrack 中,我们首先判断当前行是否已经放置了皇后。如果已经放置完毕,则将当前的解加入到结果集中。否则,我们遍历当前行的每一列,尝试将皇后放置在该列上。如果该列、该正斜线和该反斜线上都没有皇后,则将皇后放置在该位置上,并将该位置标记为有皇后。接着,我们递归遍历下一行。如果当前的放置方案不行,则撤销该方案,将该位置标记为无皇后,并继续遍历下一列。 最后,我们使用函数 generateBoard 将每个解转化为棋盘的形式,并将其加入到结果集中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值