1

Тема: Завдання про n ферзів на дошці n x n

Потрібно знайти кількість рішень того, як можна розмістити n ферзів на шаховій дошці n x n так, щоб вони не били одне одного.

Ось що в мене вийшло:

using namespace std;

class Solution {

    bool is_not_under_attack(vector<vector<int>>& board, int& row, int& col)
    {
        bool answer { true };
        if (board.at(row).at(col) != 0) {
            answer = false;
        }
        return answer;
    }

    void place_queen(vector<vector<int>>& board, const int& n, int row, int col)
    {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (board.at(i).at(j) == 0 && (i == row || j == col || (i - row == j - col) || (i + j == col + row))) {
                    board.at(i).at(j) = 1;
                }
            }
        }
    }

    void remove_queen(vector<vector<int>>& board, const int& n, int row, int col)
    {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (board.at(i).at(j) != 0 && (i == row || j == col || (i - row == j - col) || (i + j == col + row))) {
                    board.at(i).at(j) = 0;
                }
            }
        }
    }

    int backtrack_nqueens(vector<vector<int>>& board, const int& n, int row, int count)
    {
        for (int col = 0; col < n; ++col) {
            if (is_not_under_attack(board, row, col)) {
                place_queen(board, n, row, col);
                if (row + 1 == n) {
                    ++count;
                } else {
                    count = backtrack_nqueens(board, n, row + 1, count);
                }
                remove_queen(board, n, row, col);
            }
        }
        return count;
    }

public:
    int totalNQueens(int n)
    {
        vector<vector<int>> board(n, vector<int>(n, 0));
        int answer = backtrack_nqueens(board, n, 0, 0);
        return answer;
    }
};
int main()
{

    int n { 4 };

    Solution obj;
    int answer = obj.totalNQueens(n);
    cout << answer << endl;

    return 0;
}

Але десь там помилка і я не знаю, де саме.
Забагато рішень нараховує.

2

Re: Завдання про n ферзів на дошці n x n

Перемудрив із розміщенням і видаленням ферзя, недомудрив із перевіркою.
Ось як треба було, але це без оптимізації:

class Solution {
    bool is_not_under_attack(vector<vector<int>>& board, int row, int col, int n)
    {

        for (int i = 0; i < row; i++) {
            if (board.at(i).at(col)) {
                return false;
            }
        }

        for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
            if (board.at(i).at(j)) {
                return false;
            }
        }
        for (int i = row, j = col; i >= 0 && j < n; j++, i--) {
            if (board.at(i).at(j)) {
                return false;
            }
        }
        return true;
    }

    int backtrack_nqueens(vector<vector<int>>& board, const int& n, int row, int count)
    {
        for (int col = 0; col < n; ++col) {
            if (is_not_under_attack(board, row, col, n)) {
                board.at(row).at(col) = 1;
                if (row + 1 == n) {
                    ++count;
                } else {
                    count = backtrack_nqueens(board, n, row + 1, count);
                }
                board.at(row).at(col) = 0;
            }
        }
        return count;
    }

public:
    int totalNQueens(int n)
    {
        vector<vector<int>> board(n, vector<int>(n, 0));

        return backtrack_nqueens(board, n, 0, 0);
    }
};

3

Re: Завдання про n ферзів на дошці n x n

По-перше, припиніть уже писати .at(). Є нормальний оператор [].
А по-друге, спробуєте переробити рекурсію на цикл? Вам треба продумати процедуру переходу від однієї валідної, але, можливо, незавершеної позиції до наступної.

Подякували: steamwater, leofun012

4

Re: Завдання про n ферзів на дошці n x n

koala написав:

По-перше, припиніть уже писати .at(). Є нормальний оператор [].
А по-друге, спробуєте переробити рекурсію на цикл? Вам треба продумати процедуру переходу від однієї валідної, але, можливо, незавершеної позиції до наступної.

.at() наче кращий за [], бо повідомляє, коли індекс виходить за межі контейнера.
Це завдання з Leetcode Explore Recusion II, там потрібна саме рекурсія.

5

Re: Завдання про n ферзів на дошці n x n

Він просто інший.
Якщо ви не певні, чи індекс в межах масиву, то at може бути й стерпним. Але яким чином він тут вийде? Всі розміри - до n.

6

Re: Завдання про n ферзів на дошці n x n

koala написав:

Він просто інший.
Якщо ви не певні, чи індекс в межах масиву, то at може бути й стерпним. Але яким чином він тут вийде? Всі розміри - до n.

Захоче і вийде, він такий:).
Я тут подумав, що все одно в мене pedantic увімкнено в налаштуваннях CMake,
а він перевіряє межі для []. Тому, мабуть, дійсно немає сенсу використовувати at() у такому разі.

7

Re: Завдання про n ферзів на дошці n x n

Teg Miles написав:

Захоче і вийде, він такий

Метод at() нічим не кращий, окрім того, що муляє око.
Я ж вам вже давав налаштування.. Ввімкніть санітайзер, він зробить bounds-checking перевірки для вас, pedantic btw тут ні до чого.

Подякували: leofun011

8

Re: Завдання про n ферзів на дошці n x n

wander написав:
Teg Miles написав:

Захоче і вийде, він такий

Метод at() нічим не кращий, окрім того, що муляє око.
Я ж вам вже давав налаштування.. Ввімкніть санітайзер, він зробить bounds-checking перевірки для вас, pedantic btw тут ні до чого.

Санітайзер увімкнутий теж, думав, що pedantic за це відповідає.

9

Re: Завдання про n ферзів на дошці n x n

wander написав:
Teg Miles написав:

Захоче і вийде, він такий

Метод at() нічим не кращий, окрім того, що муляє око.
Я ж вам вже давав налаштування.. Ввімкніть санітайзер, він зробить bounds-checking перевірки для вас, pedantic btw тут ні до чого.

Вiн не муляє. Те що його довше набирати те не що, порiвняно з тим, що воно потребує двi додатковi перевiрки (лiва та права межi iнтервалу). Я це вже намагався пояснити ТС, але марно, покi що. Може колись сам зрозумiє, але впертий дуже. Доречi, впертiсть є непоганою порукою, щоб стати непоганим програмiстом :D

Подякували: leofun011

10 Востаннє редагувалося steamwater (20.09.2024 11:47:14)

Re: Завдання про n ферзів на дошці n x n

Teg Miles написав:
koala написав:

Він просто інший.
Якщо ви не певні, чи індекс в межах масиву, то at може бути й стерпним. Але яким чином він тут вийде? Всі розміри - до n.

Захоче і вийде, він такий:).
Я тут подумав, що все одно в мене pedantic увімкнено в налаштуваннях CMake,
а він перевіряє межі для []. Тому, мабуть, дійсно немає сенсу використовувати at() у такому разі.

Тут одразу 2 приклади гарячого бажання використати iнструмент без будь-якого розумiння як вiн працює. Teg Miles, мова С++ це унiкальний засiб втiлення неймовiрної кiлькостi iнструментiв. Якщо ви обрали С++, то маєте змiнити пiдхiд. Не використовуйте iнструмент, якщо можете. Ключ pedantic перевiряє вiдповiднiсть стандарту. Це стосується сiнтаксису та корректностi використання виразiв. Та головне, мабуть, полягає у тому, що це ключ компiлятора i працює воно саме на стадiї компiляцiї. Перевiркi у методi at вектора, виконуюються на стадiї виконання. Питання ж не тiлькi у тому що ви одержуєте не просто ще 2 перевiрки, а щось накшалт:

if(ind < vec.last - vec,data + 1 || ind > vec,data - 1)
throw(bad_index); // це ще трохи коду
// далi робота з ind

там окрiм двох прорiвняннь, ще обчислювання. Звертання до внутрешнього буфера data (вказiвника на кучу, фактично), здiйснюється через об'єкт вектора.
Teg Miles, на С++ треба добре розумiти деталi. Для цього, треба ними цiкавитися i копати. Якщо воно вам не подобається, то треба задати собi питання, а воно потрiбно? Тут треба багато робити самому, але коли вже вам кажуть з боку, то треба все кидати й роздивлятися. Неможна всього навчитись на форумах. Але якщо, навiть коли те що приходить у такий спосiб, вперто iгнорується, це вже бiда на iншому рiвнi. Треба кардiнально змiнювати пiдхiд, або кидати цю нудну справу.