c++n-queens

Why the "if" didn't work ? (n queen problem)


here is my code

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

int k = 4;
vector<int> QLocation(k,0);
vector<vector<string> > board(k, vector<string>(k, "."));

bool check(int row, int column)
{
    if (row == 0) return true;

    for (int m = row - 1, n = 1; m >= 0; m--, n++)
    {
        if (board[m][column] == "Q") return false;
        if (column + n < n && board[m][column + n] == "Q") return false;
        if (column - n >= 0 && board[m][column - n] == "Q") return false;
    }
    return true;
}

void solve(int row, int column)
{
    for (int i = row; i < k;i++)
    {
        for (int j = column; j < k; j++)
        {
            if (check(i, j))
            {
                board[i][j] = "Q";
                QLocation[i] = j;
                break;
            }
            else
                board[i][j] = ".";

            if (j == k - 1)
            {
                i -= 1;
                j = QLocation[i];
            }
        }
    }
}

int main()
{    
    solve(0, 0);
    for (int i = 0; i < k; i++)
    {
        for (int j = 0; j < k; j++)
            cout << board[i][j];
        cout << endl;
    }
}

The output is infinite loop

I set breakpoints on lines 11, 15, 16, 17, and 28 to check the value change step by step

When i=2, j=1, enter the check and when m=1, n=1, board[m][column + n] == "Q" but does not return false enter image description here

why?

====== 2021/08/25 22:00 update ======

when i delete these code and k=4

if (j == k - 1)
{
    i -= 1;
    j = QLocation[i];
}

the output is

Q...
..Q.
.Q..
....

when k=8 output is

Q.......
..Q.....
.Q......
.....Q..
.......Q
...Q....
........
....Q...

the third row always fail, but the other rows all correct


Solution

  • Edit: This answer assumes you have corrected the typo in if(column + n < n ...) to if(column + n < k ...)

    The problem is in this part

    if(j == k-1){
       i -= 1;
       j = Qlocation[i];
    }
    

    consider the case of k = 4 and i = 2 in the iteration. The board will be looking like this at that point.

    Q...
    ..Q.
    ....
    ....
    

    and here check(i, j) is always false for i = 2, so i goes back to 1. But you are not changing the value of board[i][Qlocation[i]] back to '.'. This is one mistake(Even if you correct this, it won't work. I am gonna tell you why assuming you corrected that by adding board[i][j] = "." after j = Qlocation[i];). Now the values are i = 1, j = 3(j++ in for-loop). The check returns true, you place a queen there, and i increases to 2.

    The board:

    Q...
    ...Q
    ....
    ....
    

    Here, check(i, j) returns true for j = 1. The board:

    Q...
    ...Q
    .Q..
    ....
    

    Now i = 3. check(i, j) fails for all j. i decreases to 2 and j to 2(j = Qlocation(i), j++). check(i, j) fails for (2, 2) and (2, 3), on which point i further decreases to 1, and j to 4 (j = Qlocation(1), j++).

    The board:

    Q...
    ....
    ....
    ....
    because of board[i][j] = ".";
    

    Now j = 4 does not satisfy the condition j < k, so the inner for-loop breaks, and the outer for loop iterates to increase i to 2. check(i, j) return true for j = 1. The board:

    Q...
    ....
    .Q..
    ....
    

    Now i = 3, check(i, j) fails for all j, i becomes 2. check(i, j) returns true for j = 3.The board:

    Q...
    ....
    ...Q
    ....
    

    Now again i = 3, check(i, j) returns true for j = 1. The final answer:

    Q...
    ....
    ...Q
    .Q..
    

    which is wrong. So, you have to add a check whether the for loop exits without any Q in the row.