算法之n皇后

本文探讨了N皇后问题,这是一个经典的回溯算法案例。目标是在N×N的棋盘上放置N个皇后,确保任意两个皇后都不会互相攻击。文章详细介绍了通过递归和回溯方法寻找所有可能的解决方案,展示了如何使用特定的算法来检查每个皇后的位置是否有效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

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

示例:

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

["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]

一行一行地落子,每一行都只能落一个字,然后尝试在0~n-1地每一个位置都落子; 如果能够落子,那么 考虑下一行,如果不能就gg

class Solution {
        List<List<String>> res=new LinkedList<>();
        public List<List<String>> solveNQueens(int n) {
            List<String> list=new LinkedList<>();
            int[]pos_record=new int[n];

            set_cur(n,0,-2,list,pos_record);

            return res;
        }

//这样比较耗空间,list可以在row==n-1时,根据 pos_record来添加进去
        void set_cur(int n,int row,int pre_pos,List<String> list,int[] pos_record){

            //先看一下这个位置能不能落子,在位置i落子
                for(int i=0;i<n;i++){

                    if(is_addable(pos_record,row,i)){
                        List<String> new_list=new LinkedList<>(list);
                        int[] new_pos_record=new int[n];
                        for(int k=0;k<n;k++){
                            new_pos_record[k]=pos_record[k];
                        }


                        //那么这里是可以落子的
                        String s="";
                        for(int j=0;j<n;j++){
                            if(j==i){
                                s+="Q";
                            }
                            else {
                                s+=".";
                            }
                        }
                   //     System.out.print(s+"\n");
                        new_list.add(s);
                        if(row== n-1){
                            //如果已经是最后一行
                            res.add(new_list);
                          //  System.out.print("im");
                        }
                        else {
                            new_pos_record[row]=i;//第row行落子到位置i上
                            set_cur(n,row+1,i,new_list,new_pos_record);
                        }
                    }
                }


        }

        boolean  is_addable(int []record,int row,int pos){
            for(int i=0;i<row;i++){
                //什么情况下不能落子?
                if(record[i]==pos||Math.abs(pos-record[i])==Math.abs(row-i)){
                    return false;
                }
            }
            return true;
        }
    }
### 关于N皇后问题的回溯算法实现及解析 #### 一、N皇后问题简介 N皇后问题是经典计算机科学难题之一,旨在找到一种方法,在\( N \times N \)大小的国际象棋棋盘上放置 \( N \)个皇后,让这些皇后互不攻击对方。这意味着任何两个皇后都不能处于同一行、同一列或相同对角线之上[^1]。 #### 二、回溯算法原理 回溯是一种通过尝试所有可能解决方案来解决问题的方法;如果当前方案无法继续,则返回前一步重新选择其他路径直到找到解为止。对于N皇后问题而言,就是逐行摆放皇后并验证合法性,当某一行无合适位置时则撤销最近一次操作再试下一处,直至完成全部皇后的安置或是遍历完所有可能性[^2]。 #### 三、具体实现过程 为了更好地理解这一逻辑流程,下面给出Python版本的具体代码示例: ```python def solve_n_queens(n): result = [] def is_not_under_attack(row, col): return not (cols[col] + hill_diagonals[row - col] + dale_diagonals[row + col]) def place_queen(row, col): queens.add((row, col)) cols[col], hill_diagonals[row - col], dale_diagonals[row + col] = True, True, True def remove_queen(row, col): queens.remove((row, col)) cols[col], hill_diagonals[row - col], dale_diagonals[row + col] = False, False, False def backtrack(row=0, count=0): for col in range(n): if is_not_under_attack(row, col): place_queen(row, col) if row + 1 == n: result.append(queens.copy()) count += 1 else: count = backtrack(row + 1, count) remove_queen(row, col) return count cols = [False] * n hill_diagonals = [False] * (2 * n - 1) dale_diagonals = [False] * (2 * n - 1) queens = set() total_solutions = backtrack() board_formatting = lambda queens: ['.'*i + 'Q' + '.'*(n-i-1) for i in sorted(list({q[1] for q in queens}))] formatted_boards = list(map(board_formatting, result)) return formatted_boards, total_solutions if __name__ == "__main__": solutions, num_of_solutions = solve_n_queens(8) print(f"Total number of distinct solutions to the {len(solutions)} Queens puzzle:") for solution in solutions[:min(len(solutions), 3)]: for line in solution: print(line) print("") ``` 上述程序定义了一个`solve_n_queens`函数用于求解给定规模下的N皇后问题,并打印部分结果作为展示[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值