Расставить на шахматной доске 8х8, 8 ферзей так, чтобы ни один их них не мог быть атакован другим

Есть задача с расстановкой на шахматной доске 8х8, 8 ферзей так, чтобы ни один из них не мог быть атакован другим. Решить нужно простой проверкой элементов доски по горизонтали, вертикали и диагоналям соответственно текущей позиции вставки на доске. 0 на доске соответствуют пустой позиции, 1-установленному ферзю.

Есть код:

#include <iostream>
using namespace std;

bool SVert(int arr[8][8], int i, int j)
{
    bool inf = true;
    for (int i = 0; i < 8; i++)
    {
        if (arr[j][i] == 1)
        {
            inf = false;
            return inf;
        }

    }
    return inf;
}

bool SHor(int arr[8][8], int i, int j)
{

    bool inf = true;
    for (int j = 0; j < 8; j++)
    {
        if (arr[i][j] == 1)
        {
            inf = false;
            return inf;
        }
    }
    return inf;
}

bool SDiag(int arr[8][8], int i, int j)
{
    bool d1 = true, d2 = true, inf = true;

    return inf;
}

void Nulification(int arr[8][8])
{
    for (int i = 0; i < 8; i++)
        for (int j = 0; j < 8; j++)
            arr[i][j] = 0;
}

void Show(int arr[8][8])
{
    for (int i = 0; i < 8; i++) 
    {
        for (int j = 0; j < 8; j++)
            cout << arr[i][j]<<" ";
        cout << endl;
    }
    cout << endl;
}

void Ferzification(int arr[8][8])
{
    int counter = 0;
    while (counter < 8)
    {
        for(int i=0;i<8;i++)
            for(int j=0; j<8; j++)
                if (SVert(arr,i,j) && (SHor(arr, i, j)) && (SDiag(arr, i, j)))
                {
                    arr[i][j] = 1;
                    counter++;
                }
    }
    cout << "Ferzificated board: " << endl;
    Show(arr);
}

int main()
{
    cout << "Our Board: " << endl;
    int arr[8][8];
    Nulification(arr);
    Show(arr);
    Ferzification(arr);
    return 0;
}

Нужно дописать функцию проверки на 2 горизонтали, которая вернет True, если на обеих горизонталях, относительно позиции вставки нет ферзя, но что-то совсем мысли в голову не идут, хотя дело элементарно.


Ответы (1 шт):

Автор решения: Harry

А можно, я предложу способ проще? Итак, очевидно, что два ферзя на одной вертикали стоять не могут. Поэтому напишем рекурсивную функцию vert(i) установки ферзя в i-й вертикали. Которая просто поочередно проверяет все клетки, и если можно - ставит ферзя и рекурсивно вызывает vert(i+1). Если добрались до 8-й вертикали (несуществующей) - ура, все расставлено. Если где-то нельзя - идет возврат 0, и на предыдущей вертикали новая попытка.

int board[8][8]; // Доска; 1 - ферзь

int chk(int c, int r)  // Проверка, что можно ставить в клетку [r][c] 
{                      // проверка - только слева!
    for(int i = 0; i < c; ++i)
    {
        // Проверка горизонтали
        if(board[i][r]) return 0;
        // Проверка диагонали
        if (r-c+i>=0) if (board[i][r-c+i]) return 0;
        if (r+c-i< 8) if (board[i][r+c-i]) return 0;
    }
    return 1;
}

// Сама рекурсивная функция
int vert(int i) // Установка i-й вертикали
{
    if (i == 8) return 1;  // Ура, расставили
    for(int j = 0; j < 8; ++j)  // Ищем место по ввертикали
        if (chk(i,j))           // Если можно - 
        {
            board[i][j] = 1;    // ставим
            if (vert(i+1)) return 1; // получилось!
            board[i][j] = 0;    // не получилось - убираем ферзя
        }
    return 0;
}

int main(int argc, char * argv[])
{
    vert(0);
    // ... и сам вывод ...
    for(int i = 0; i< 8; ++i)
    {
        for(int j = 0; j< 8; ++j)
            cout << (board[i][j] ? '#' : '.');
        cout << endl;
    }
}

А вот как это работает - https://ideone.com/b5hwIW

→ Ссылка