我正在努力解决这个问题,作为我即将进行的测试的练习练习。它要求我用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上都有。只有我已经使用过的信息)。任何帮助将不胜感激!! :)
答案 0 :(得分:0)
您的“右上角”签入findOpenSpot
(最后一次while循环)条件不正确。由于您在该循环中递增j
,因此需要检查j
是否低于数组的上限,而不是与零进行比较。
while (i >= 0 && j < size)
这也将使用当前未使用的size
参数。如果使用足够高的警告级别进行编译,编译器会告诉您size
是一个未使用的参数,这将是一个有问题的线索。