题解 | N皇后问题

N皇后问题

https://www.nowcoder.com/practice/c76408782512486d91eea181107293b6?tpId=295&tqId=1008753&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page

class Solution {
  public:
    int Nqueen(int n) {
        int count = 0;
        vector<int> position(n, 0); // position[i]表示第i行皇后放在第几列
        backtrack(0, n, position, count);
        return count;
    }

  private:
    void backtrack(int row, int n, vector<int>& position, int& count) {
        if (row == n) {
            // 所有行都放置完毕,找到一个解
            count++;
            return;
        }

        // 尝试在当前行的每一列放置皇后
        for (int col = 0; col < n; col++) {
            if (isValid(row, col, position)) {
                position[row] = col; // 放置皇后
                backtrack(row + 1, n, position, count); // 递归到下一行
                // 回溯:不需要显式重置position[row],因为会被覆盖
            }
        }
    }

    bool isValid(int row, int col, const vector<int>& position) {
        // 检查当前位置(row, col)是否合法
        for (int i = 0; i < row; i++) {
            // 检查是否在同一列
            if (position[i] == col) {
                return false;
            }
            // 检查是否在同一对角线:行差 == 列差
            if (abs(row - i) == abs(col - position[i])) {
                return false;
            }
        }
        return true;
    }
};

// 共同的回溯框架
void backtrack(当前状态) {
    if (到达终止条件) {
        记录解;
        return;
    }
    
    for (所有可能的选择) {
        if (选择合法) {
            做选择;
            backtrack(下一状态);
            撤销选择;
        }
    }
}

全排列和N皇后问题回溯都是自动的,递归调用返回时都发生回溯;制权都返回到上一层的for循环;会继续尝试下一个选择
撤销操作不是"不自动回溯"的证据,而是不同状态管理策略的体现。回溯的核心机制——递归返回后继续循环——在两种算法中是完全相同的!
撤销选择更深层的设计原则:
何时需要显式撤销?
状态会累积或影响后续决策
状态改变是添加式的而非替换式的
状态需要在回溯后恢复到之前的确切值

何时可以依赖覆盖?
每个决策点的状态是独立的
状态存储是固定大小的数组
新的选择会自然覆盖旧的选择

递归/回溯 文章被收录于专栏

递归 (Recursion) 递归是函数调用自身的一种编程技巧,包含两个关键部分: 基线条件:递归终止的条件 递归条件:函数调用自身的条件 回溯 (Backtracking) 基本概念 回溯是一种通过&quot;试错&quot;来寻找问题解的算法,当发现当前路径不能得到有效解时,会退回上一步尝试其他可能性。 核心思想:深度优先搜索 + 状态重置

全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务