Задача о 8 ферзях, но с исключением симметрий на c++

Рейтинг: 0Ответов: 1Опубликовано: 10.07.2023

В обычной задаче о 8 ферзях просто выводится 92 решения, но мне задали сделать так, чтобы в задаче выводились только не симметричные решения, т. е:

Q . . . . . . .
. . . . Q . . .
. . . . . . . Q
. . . . . Q . .
. . Q . . . . .
. . . . . . Q .
. Q . . . . . .
. . . Q . . . .
Result #1 

симметричен с по вертикали:

. . . . . . . Q
. . . Q . . . .
Q . . . . . . .
. . Q . . . . .
. . . . . Q . .
. Q . . . . . .
. . . . . . Q .
. . . . Q . . .
Result #92

и с по горизонтали:

. . . Q . . . .
. Q . . . . . .
. . . . . . Q .
. . Q . . . . .
. . . . . Q . .
. . . . . . . Q
. . . . Q . . .
Q . . . . . . .
Result #33

У меня даже теоретически нет понятия, как это реализовать, а методом проб и ошибок я не успею сдать вовремя. Очень буду рад помощи.

Так же, вот весь код с выводом всех решений:

#include "stdafx.h"
#include <iostream>
 
using namespace std;

const int SIZE = 8; 
 
int board[SIZE][SIZE];
int results_count = 0; 
 
void showBoard()
{
    for(int a = 0; a < SIZE; ++a)
    {
        for(int b = 0; b < SIZE; ++b)
        {
            cout << ((board[a][b]) ? "Q " : ". ");
        }
        cout << endl;
    }
}
 
bool tryQueen(int a, int b)
{
    for(int i = 0; i < a; ++i)
    {
        if(board[i][b])
        {
            return false;
        }
    }
    
    for(int i = 1; i <= a && b-i >= 0; ++i)
    {
        if(board[a-i][b-i])
        {
            return false;
        }
    }
    
    for(int i = 1; i <= a && b+i < SIZE; i++)
    {
        if(board[a-i][b+i])
        {
            return false;
        }
    }
    
    return true;
}
 
void setQueen(int a) 
{
    if(a == SIZE)
    {
        showBoard();
        cout << "Result #" << ++results_count << endl << endl;
        return; 
    }
    
    for(int i = 0; i < SIZE; ++i)
    {

        if(tryQueen(a, i))
        {
            board[a][i] = 1;
            setQueen(a+1);
            board[a][i] = 0;
        }
    }
    
    return; 
}
 
int main()
{
    setQueen(0);
    
    system("pause");
}

Ответы

▲ 3Принят

Решений немного, просто добавьте проверку, не было ли уже такого решения. Например, сразу, получив решение, добавляйте его и симметричные ему в set. Если что-то не добавилось — значит, симметричное решение уже было. Типа

if(a == SIZE)
{

    if (!solution()) return;
    showBoard();
    cout << "Result #" << ++results_count << endl << endl;

где проверка

set<int> sols;
...

bool solution()
{
    int s[SIZE];
    for(int i = 0; i < SIZE; ++i)
    {
        for(int j = 0; j < SIZE; ++j)
        {
            if (board[i][j])
            {
                s[i] = j;
                break;
            }
        }
    }

    int S[3]{};
    for(int i = 0; i < SIZE; ++i)
    {
        S[0] = S[0] * SIZE + s[i];
        S[1] = S[1] * SIZE + s[SIZE - i - 1];   // Симметрия по горизонтали
        S[2] = S[2] * SIZE + SIZE - s[i] - 1;   // Симметрия по вертикали
    }
    for(int i = 0; i < 3; ++i)
    {
        // Симметричные т.о. решения не могут совпадать, проверка не нужна
        auto res = sols.insert(S[i]);
        if (res.second == false) return false;
    }
    return true;
}

Но!!! Вы упомянули только две симметрии — по горизонтали и вертикали! И код написан только для них. Но есть еще симметрия осевая и поворотная. (Хотя осевая и так отсеивается при отсеве симметрий по горизонтали и вертикали...) Если они тоже нужны — надо внести соответствующие добавления и проверки в код. Оставлю это в качестве "задания читателю", раз вы о них не упомянули...

P.S. Вот тут я как-то игрался, интересно было получить числа расстановок для разных досок (сами расстановки не выводил), можете посмотреть.

P.P.S. Метод работает при обычном set<int> из VC++ (а на него намекает #include "stdafx.h") до 9х9, а если взять set<unsigned long long>, то до 16x16.

UPDATE

Полное решение, расписал через вспомогательные массивы, с проверкой и записью минимального значения (см. обсуждение к комментариях).

bool solution()
{
    int s[8][SIZE];
    for(int i = 0; i < SIZE; ++i)
    {
        for(int j = 0; j < SIZE; ++j)
        {
            if (board[i][j])
            {
                s[0][i] = j;
                break;
            }
        }
    }
    for(int i = 0; i < SIZE; ++i)
    {
        // Обработка ВСЕХ, даже лишних :) симметрий.
        s[1][i] = SIZE-1-s[0][i];
        s[2][SIZE-1-i] = s[0][i];
        s[3][SIZE-1-i] = SIZE-1-s[0][i];
        s[4][s[0][i]] = i;
        s[5][s[0][i]] = SIZE-1-i;
        s[6][SIZE-1-s[0][i]] = i;
        s[7][SIZE-1-s[0][i]] = SIZE-1-i;
    }

    int S[8]{};
    for(int i = 0; i < 8; ++i)
    {
        for(int j = 0; j < SIZE; ++j)
        {
            S[i] = S[i] * SIZE + s[i][j];
        }
    }
    sort(S,S+8);
    auto res = sols.insert(S[0]);

    // Лучше эти две строки заменить на
    // auto res = sols.insert(*min_element(S,S+8));

    if (!res.second) return false;
    return true;
}

Вот решения:

Q . . . . . . . 
. . . . Q . . . 
. . . . . . . Q 
. . . . . Q . . 
. . Q . . . . . 
. . . . . . Q . 
. Q . . . . . . 
. . . Q . . . . 
Result #1

Q . . . . . . . 
. . . . . Q . . 
. . . . . . . Q 
. . Q . . . . . 
. . . . . . Q . 
. . . Q . . . . 
. Q . . . . . . 
. . . . Q . . . 
Result #2

. Q . . . . . . 
. . . Q . . . . 
. . . . . Q . . 
. . . . . . . Q 
. . Q . . . . . 
Q . . . . . . . 
. . . . . . Q . 
. . . . Q . . . 
Result #3

. Q . . . . . . 
. . . . Q . . . 
. . . . . . Q . 
Q . . . . . . . 
. . Q . . . . . 
. . . . . . . Q 
. . . . . Q . . 
. . . Q . . . . 
Result #4

. Q . . . . . . 
. . . . Q . . . 
. . . . . . Q . 
. . . Q . . . . 
Q . . . . . . . 
. . . . . . . Q 
. . . . . Q . . 
. . Q . . . . . 
Result #5

. Q . . . . . . 
. . . . . Q . . 
Q . . . . . . . 
. . . . . . Q . 
. . . Q . . . . 
. . . . . . . Q 
. . Q . . . . . 
. . . . Q . . . 
Result #6

. Q . . . . . . 
. . . . . Q . . 
. . . . . . . Q 
. . Q . . . . . 
Q . . . . . . . 
. . . Q . . . . 
. . . . . . Q . 
. . . . Q . . . 
Result #7

. Q . . . . . . 
. . . . . . Q . 
. . Q . . . . . 
. . . . . Q . . 
. . . . . . . Q 
. . . . Q . . . 
Q . . . . . . . 
. . . Q . . . . 
Result #8

. Q . . . . . . 
. . . . . . Q . 
. . . . Q . . . 
. . . . . . . Q 
Q . . . . . . . 
. . . Q . . . . 
. . . . . Q . . 
. . Q . . . . . 
Result #9

. . Q . . . . . 
. . . . Q . . . 
. Q . . . . . . 
. . . . . . . Q 
Q . . . . . . . 
. . . . . . Q . 
. . . Q . . . . 
. . . . . Q . . 
Result #10

. . Q . . . . . 
. . . . Q . . . 
. . . . . . . Q 
. . . Q . . . . 
Q . . . . . . . 
. . . . . . Q . 
. Q . . . . . . 
. . . . . Q . . 
Result #11

. . Q . . . . . 
. . . . . Q . . 
. Q . . . . . . 
. . . . Q . . . 
. . . . . . . Q 
Q . . . . . . . 
. . . . . . Q . 
. . . Q . . . . 
Result #12