You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

变体N皇后问题C++实现:回溯/递归逻辑错误排查请求

Hey there! Let's work through your variant N-Queens problem. It sounds like you're hitting snags with the backtracking/recursion logic when the queen count doesn't match the board size—super common pitfall with this twist on the classic problem. Let's break down the most likely issues and how to fix them.

Common Backtracking Logic Mistakes for Variant N-Queens

1. Wrong Base Case (The #1 Culprit)

The classic N-Queens stops when you've filled every row with a queen, but your variant needs to stop as soon as you've placed k queens total—regardless of whether you've reached the last row. A lot of folks accidentally carry over the classic base case, which breaks all k < n scenarios.

Wrong (Classic N-Queens):

if (row == n) {
    saveSolution(board);
    return;
}

Correct (Variant):

if (queenCount == k) {
    saveSolution(board);
    return;
}
// Also add a guard for when we run out of rows early
if (row >= n) return;

2. Forgetting the "Skip This Row" Option

In classic N-Queens, you have to place a queen in every row. But for k < n, you can choose to leave a row empty and move to the next one. This is the most overlooked part of the variant logic—without it, your code will only generate solutions where every row has a queen (i.e., k = n).

Add this after your loop of placing queens in the current row:

// Option to place NO queen in current row, proceed to next
backtrack(row + 1, queenCount, board);

3. Broken Safety Check

Double-check your isSafe function to make sure it doesn't assume one queen per row. Since we can skip rows, the function only needs to check rows above the current one (since we process rows top to bottom):

Example Correct Safety Check:

bool isSafe(int row, int col, vector<vector<char>>& board, int n) {
    // Check same column above current row
    for (int i = 0; i < row; i++) {
        if (board[i][col] == 'Q') return false;
    }
    // Check upper-left diagonal
    for (int i = row-1, j = col-1; i >= 0 && j >= 0; i--, j--) {
        if (board[i][j] == 'Q') return false;
    }
    // Check upper-right diagonal
    for (int i = row-1, j = col+1; i >= 0 && j < n; i--, j++) {
        if (board[i][j] == 'Q') return false;
    }
    return true;
}

4. Accidental Reference Passing for Queen Count

If you pass queenCount by reference instead of value, backtracking will mess up the count across branches. Always pass it by value so each recursive call gets its own copy:

// Good: queenCount is passed by value
void backtrack(int row, int queenCount, vector<vector<char>>& board) { ... }

5. Solution Saving Errors

When saving a valid board state, make sure you copy the board into a new structure—don't store a reference. The board will be modified during backtracking, so references will overwrite your saved solutions:

void saveSolution(vector<vector<char>>& board, vector<vector<string>>& results) {
    vector<string> temp;
    for (auto& row : board) {
        temp.push_back(string(row.begin(), row.end()));
    }
    results.push_back(temp);
}
Working Minimal Example Skeleton

Here's a stripped-down C++ framework you can compare against your code:

#include <vector>
#include <string>
using namespace std;

class VariantNQueens {
private:
    vector<vector<string>> results;
    int boardSize, queenCountTarget;

    bool isSafe(int row, int col, vector<vector<char>>& board) {
        // Same as the safe check above
        for (int i = 0; i < row; i++)
            if (board[i][col] == 'Q') return false;
        for (int i = row-1, j = col-1; i >=0 && j >=0; i--, j--)
            if (board[i][j] == 'Q') return false;
        for (int i = row-1, j = col+1; i >=0 && j < boardSize; i--, j++)
            if (board[i][j] == 'Q') return false;
        return true;
    }

    void backtrack(int currentRow, int queensPlaced, vector<vector<char>>& board) {
        if (queensPlaced == queenCountTarget) {
            vector<string> sol;
            for (auto& r : board) sol.push_back(string(r.begin(), r.end()));
            results.push_back(sol);
            return;
        }
        if (currentRow >= boardSize) return;

        // Try placing a queen in each column of current row
        for (int col = 0; col < boardSize; col++) {
            if (isSafe(currentRow, col, board)) {
                board[currentRow][col] = 'Q';
                backtrack(currentRow + 1, queensPlaced + 1, board);
                board[currentRow][col] = '.'; // Backtrack
            }
        }

        // Try skipping this row entirely
        backtrack(currentRow + 1, queensPlaced, board);
    }

public:
    vector<vector<string>> solve(int n, int k) {
        boardSize = n;
        queenCountTarget = k;
        results.clear();
        vector<vector<char>> board(n, vector<char>(n, '.'));
        backtrack(0, 0, board);
        return results;
    }
};
Debugging Tips to Pinpoint Your Issue
  • Print intermediate states: Add cout statements in your backtrack function to log the current row, number of queens placed, and a snapshot of the board. This will show you exactly where the recursion is going off-track.
  • Test tiny cases first: Start with n=3, k=2. Manually list valid solutions (e.g., queens at (0,0) and (2,1)) and see if your code generates them.
  • Isolate the "skip row" branch: Comment out that line and see if your code only returns k=n solutions—if yes, that branch is working as intended when uncommented.

内容的提问来源于stack exchange,提问作者kiril

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:12:53