28-n皇后问题

本文详细介绍了N皇后问题的背景及求解思路,通过使用回溯算法,利用一位数组存储皇后位置并确保不发生冲突,最终实现了N皇后问题的有效解决。

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

leetcode52. N-Queens II

一、问题描述

n皇后拼图是将n个皇后放在n * n棋盘上的问题,使得没有两个皇后互相攻击--不能同行同列同斜线。


【需求】给定一个整数n,返回n皇后拼图的所有不同的解决方案。每个解决方案都包含n皇后位置的独特摆放情况,其中'Q'和'.' 两者分别指示女王和空闲空间。

【举例】
输入: 4   -------------  输出: 2
[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]

]   -----------------   如上所示,对于4皇后拼图存在两种截然不同的解决方案。

二、解决思路

  • 存储类型选择?

     一位数组place[i] = col,下标 i 代表特定的行,col 代表放置皇后后对应的列。

  • 如何避免冲突?
  1. 不在同一行:依据选择的存储类型---按照行存储,保证了一行一个皇后
  2. 不在同一列:place[i] != place[j]
  3. 不在同一对角线:主对角线 i - j 与从对角线 i + j 存在如下图关系


  • 约束条件?
  1. 不在同一列:place[i] != place[j]
  2. 不在同一主对角线:j-i != place[j] - place[i]
  3. 不在同一从对角线:j-i != - ( place[j] - place[i] )

所以,回溯的条件可以简写为:abs( i - j ) != abs( place[i] - place[j] ) || place[i] != place[j] 

参考文档:https://wenku.baidu.com/view/d1e9d6fe02020740bf1e9bce.html

三、算法实现

/**********************************************
Author:tmw
date:2018-5-14
**********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int place[100] = {0};
int count = 0;/**记录成功解个数**/
/**检测当放入第k个皇后时,会不会与之前放置的k-1个皇后的位置产生冲突**/
bool check( int array[], int k )
{
    int i;
    for( i=1; i<=k-1; i++ )
    {
        if( array[i]==array[k] || abs( array[i]-array[k] ) == abs( i-k ) )
            return false;
    }
    return true;
}

/**n皇后问题  -- n为所求的n皇后值,k为当前皇后值**/
void Queen( int n, int k )
{
    /**当n皇后都放置好了,说明有一组成功解**/
    if( k>n ) count++;

    /**当n个皇后并没有放置好,则执行下述操作**/
    else
    {
        int i;
        /**遍历各个列,找到合适的位置放皇后**/
        for( i=1; i<=n; i++ )
        {
            place[k] = i;

            if( check(place, k) ) /**第k个皇后满足插入条件,则继续放置第k+1个皇后**/
                Queen( n, k+1 );
        }
    }
    return;
}


int totalNQueens(int n)
{
    /***count是全局变量,每一次得出结果得清零,否则会一直累加~*/
    count = 0;
    Queen(n,1);
    return count;
}

四、运行结果

leetcode accept



梦想还是要有的,万一实现了呢~~~ヾ(◍°∇°◍)ノ゙~~~~




### 八皇后问题的时间复杂度分析 八皇后问题是一个经典的回溯算法问题。在解决该问题时,通常会使用穷举法或回溯法来寻找所有可能的解。 #### 穷举法的时间复杂度 如果采用穷举法解决八皇后问题,则需要尝试所有的棋盘布局可能性。对于一个8×8的棋盘,每个位置可以放置或不放置皇后,因此总的可能性数为 \(8^8 = 16,777,216\) 种情况[^1]。此外,在每种布局中,还需要检查是否满足皇后之间互不攻击的条件,这需要进行 \(C_8^2 = 28\) 次比较。因此,穷举法的时间复杂度为 \(O(N^N)\),其中 \(N=8\)。 #### 回溯法的时间复杂度 回溯法通过逐步构造解并及时剪枝的方式减少了不必要的搜索路径。虽然理论上回溯法仍然需要探索所有可能的情况,但由于剪枝的存在,实际的搜索空间远小于穷举法。回溯法的时间复杂度通常被认为是指数级的 \(O(2^N)\) 或 \(O(N!)\)[^2],具体取决于实现方式和剪枝策略的有效性。 在八皇后问题中,回溯法的效率主要取决于以下几个因素: 1. **剪枝策略**:通过提前判断某些布局是否可行(如检查列、主对角线和副对角线是否有冲突),可以显著减少搜索空间。 2. **递归深度**:由于棋盘大小固定为8×8,递归深度最多为8层,因此回溯法的实际运行时间是可以接受的。 #### 算法效率比较 - 穷举法的时间复杂度为 \(O(N^N)\),计算量极大,不适合解决大规模问题。 - 回溯法的时间复杂度为 \(O(2^N)\) 或 \(O(N!)\),尽管仍为指数级,但通过剪枝可以大幅降低实际运行时间[^3]。 在实际应用中,回溯法是解决八皇后问题的更优选择,尤其是在棋盘规模较小时(如8×8)。随着棋盘规模的增加,即使使用回溯法,计算量也会迅速增长,因此可能需要考虑更高效的算法或优化策略。 ```python def is_safe(board, row, col): # 检查列是否有冲突 for i in range(row): if board[i][col] == 1: return False # 检查主对角线是否有冲突 for i, j in zip(range(row, -1, -1), range(col, -1, -1)): if board[i][j] == 1: return False # 检查副对角线是否有冲突 for i, j in zip(range(row, -1, -1), range(col, len(board))): if board[i][j] == 1: return False return True def solve_n_queens_util(board, row): if row == len(board): return ["".join(["Q" if x == 1 else "." for x in r]) for r in board] solutions = [] for col in range(len(board)): if is_safe(board, row, col): board[row][col] = 1 solutions += solve_n_queens_util(board, row + 1) board[row][col] = 0 return solutions def solve_n_queens(n): board = [[0 for _ in range(n)] for _ in range(n)] return solve_n_queens_util(board, 0) # 示例调用 solutions = solve_n_queens(8) print(f"Total solutions: {len(solutions)}") ``` ### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值