N-Queens 回溯/递归逻辑错误?

Posted

技术标签:

【中文标题】N-Queens 回溯/递归逻辑错误?【英文标题】:N-Queens Backtracking/Recursion Logic Errors? 【发布时间】:2018-03-30 02:24:27 【问题描述】:

我正在尝试解决这个问题,作为我即将进行的测试的练习。它要求我用 C++ 编写一个程序,要求输入“棋盘大小”(nxn)和“皇后数”,然后执行“n 皇后”问题。

这个 n-queens 问题与“正常”n-queens 问题的不同之处在于,皇后的数量和棋盘大小可以变化,如果棋盘没有完全填满,则开放空间被替换了。

输入大小为“8”和皇后号“4”的示例输出如下所示:

O.......
..O.....
....O...
.O......
...­-..­.-
........
...­-.-..
...­-.­.-.

其中“O”代表一个被皇后占据的空间,“.”表示被另一个皇后挡住的空间,'-' 表示如果用户输入了更多数量的皇后(即开放空间),则 可能被另一个皇后占据的空间。

问题是,我已经把问题编码出来了,它给了我极度不一致的结果。 (例如:输入 4,4 个作品,5,5 个作品,6,6 个工作,7,7 个作品,8,8 个工作,2 ,1 工作....这个列表还在继续)。我发现罪魁祸首是“for”循环和完成后返回堆栈的递归的组合,根据情况导致了几个错误。我的问题是,我将如何修复递归循环,以便它仍然能够回溯,同时也不会不必要地导致错误?我对“回溯”加上递归的想法很陌生;以后我可以做些什么来改进我的回溯方法?

我的代码如下:

#include <iostream>
#include <cstdlib>
using namespace std;

void readBoard(char board[100][100], int size);
void printBoard(char board[100][100], int size);
bool findOpenSpot(char board[100][100], int row, int col, int size);
bool nQueenSolver(char board[100][100], int row, int size, int queenNumber);

int main()

    int queenNumber;
    int size;
    char b[100][100];
    cout << "What size board do you want?" << endl;
    cin >> size;
    readBoard(b, size);
    printBoard(b, size);
    cout << "How many queens do you want to place?" << endl;
    cin >> queenNumber;
    if (queenNumber > size)
    
        cout << "Impossible." << endl;
        exit(0);
    
    if (nQueenSolver(b, 0, size, queenNumber) == true)
    
        printBoard(b, size);
    
    else
    
        cout << "Impossible." << endl;
    
    return 0;


bool nQueenSolver(char board[100][100], int row, int size, int queenNumber)

    if (row >= size)
    
        return true;
    

    for (int j=0; j<size; j++)
    
        if (findOpenSpot(board, row, j, size) == true)
        
            if (queenNumber >= 0)
            
                board[row][j] = 'Q';
                cout << "Subtracting one queen." << endl;
            
            else if (queenNumber < 0)
            
                board[row][j] = '-'; //If all queens have already been placed, start showing open slots.
            
            if (nQueenSolver(board, row+1, size, queenNumber) == true) //Recursion to cycle down the rows
            
                return true; 
            
            board[row][j] = '.'; //Backtracking if needed.
        

    
    return false;


bool findOpenSpot(char board[100][100], int row, int col, int size)

    int i, j;
    for (i=0; i<col; i++)
    
        if (board[row][i] == 'Q') //Checks if there's any queens to the left of the index
        
            return false; //Not an open spot.
        
    
    i = row; j = col;
    while (i >= 0 && j >= 0)
    
        if (board[i][j] == 'Q') //Checks if there's any queens in the upper left diagonal of the index
        
            return false; 
        
        i--; j--;
    

    for (i=0; i<row; i++)
    
        if (board[i][col] == 'Q') //Checks if there's any queens on top of the index
        
            return false; 
        
    

    i = row; j = col;
    while (i >= 0 && j >= 0)
    
        if (board[i][j] == 'Q') //Checks if there's any queens in the upper right diagonal of the index
        
            return false;
        
        i--; j++;
    

    return true; //This index isn't threatened by a queen, go ahead and place one here!
    //Open spot!!



void readBoard(char board[100][100], int size)

    for (int i=0; i<size; i++) //Puts in the size of the board into the array.
    
        for (int j=0; j<size; j++)
        
            board[i][j] = '.';
        
    


void printBoard(char board[100][100], int size)

    for (int i=0; i<size; i++) //Prints the 'board' part of the array. (Doesn't print the entire array)
    
        for (int j=0; j<size; j++)
        
            cout << board[i][j];
        
        cout << endl;
    

我也尝试在网上寻求帮助,但没有找到任何帮助(在 *** 和谷歌上。只有我已经使用过的信息片段)。任何帮助将不胜感激!! :)

【问题讨论】:

【参考方案1】:

findOpenSpot(最后一个 while 循环)中的“右上角”检查条件不正确。由于您在该循环中递增 j,因此您需要检查 j 是否低于数组的上限,而不是与零进行比较。

while (i >= 0 && j < size)

这也将使用当前未使用的size 参数。如果您以足够高的警告级别进行编译,编译器会告诉您size 是一个未使用的参数,这将是一个有问题的线索。

【讨论】:

以上是关于N-Queens 回溯/递归逻辑错误?的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 51. N-Queens N 皇后(困难)

如何通过回溯递归地修改数组元素?

迷宫求解程序的回溯逻辑错误

Leetcode 52 N-Queens II 回溯搜索

Combination Sum

java中使用堆栈和回溯的n皇后谜题