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

时间:2018-03-30 02:24:28

标签: c++ recursion backtracking n-queens

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

这个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;
    }
}

我也试过在网上寻求帮助,但没有发现(在stackoverflow和google上都有。只有我已经使用过的信息)。任何帮助将不胜感激!! :)

1 个答案:

答案 0 :(得分:0)

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

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

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