Неправильный выход с N Queen

Итак, я должен решить модифицированную версию задачи о N ферзях, где нам дана начальная конфигурация шахматной доски, заполненной пешками, и нам нужно найти максимальное количество ферзей, которое у нас может быть, чтобы они не атаковали каждую из них. Другой. Входные данные состоят из целого числа в первой строке, задающего размер доски (NxN), и n строк, определяющих настройку шахматной доски. Символы будут либо «p» (что означает, что в этом месте уже есть пешка) или «е» (что означает, что ячейка пуста).

Например, для этого ввода

5
epepe
ppppp
epepe
ppppp
epepe

выход будет 9.

Вот мой код, вроде все понятно, но я не понимаю, почему он не выдает правильный вывод

#include <stdio.h>
#include <malloc.h>

/* function headers */
void do_case(int);
int solve(char **,int,int);
int canPlace(char **,int,int,int);

/* Global vars */
int queens;

int main(void)
{
int n;
scanf("%d",&n);
getchar();
while( n != 0 )
{
    do_case(n);
    scanf("%d",&n);
    getchar();
}
return 0;
}

void do_case(int n)
{
int i,j; //counters for input

//board configuration allocation
char **configuration = (char **)malloc(n*sizeof(char *));
for(i = 0 ; i < n ;i++ ) 
    configuration[i] =(char *)malloc(n*sizeof(char));

queens = 0;

//get input
for( i = 0; i < n; i++ )
{

    for( j = 0; j < n; j++ )
    {
        scanf("%c",&configuration[i][j]);
    }
    getchar();
}

//solve
solve(configuration,n,0);
printf("%d \n",queens);




}

//recursive solver 
int solve(char **configuration,int N,int col)
{
int i,j;
//base case
if( col >= N )
    return 1;

//consider this column
//try placing queen in non blocked spot in all rows 
for(i = 0; i < N; i++)
{

    if ( configuration[i][col] == 'e' && canPlace(configuration,N,i,col) )
    {
        //Place queen in configuration[i][col]
        configuration[i][col] = 'q';
        queens++;

        //recursion on the rest
        if( solve(configuration,N,col + 1) == 1 )
        {
            return 1;
        }

        //backtrack
        configuration[i][col] = 'e'; 
        queens--;

    }
}

return 0;

}


//this function check if  queen can be placed
int canPlace(char **configuration,int N, int row, int col)
{
int i, j;

/* Check this row on left side */
for (i = 0; i < col; i++)
{
    if (configuration[row][i] == 'q')
    {
        return 0;
    }
}

/* Check upper diagonal on left side */
for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
{
    if ( configuration[i][j] == 'q')
    {

        return 0;
    }
}

/* Check lower diagonal on left side */
for (i = row, j = col; j >= 0 && i < N; i++, j--)
{
    if (configuration[i][j] == 'q')
    {

        return 0;
    }
}
return 1;
}

person user2977595    schedule 06.12.2014    source источник
comment
Нет проверки столбца в canPlace() и в левом верхнем углу   -  person chux - Reinstate Monica    schedule 07.12.2014


Ответы (2)


По сути, ваш код выводит 0, потому что он требует, чтобы мы помещали ровно одну ферзя в каждый столбец, что не так в вашем примере.

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

  1. Код не рассматривает все возможности: он найдет только первое возможное расположение, а затем прекратит поиск после единственного «if( col >= N ) return 1;». Вместо этого это должно звучать так: «if( col >= N ) обновить наилучшее возможное значение ферзей в отдельной переменной, затем вернуть 0, чтобы продолжить поиск».

  2. В строке «if(solve(configuration,N,col + 1) == 1)» код предполагает, что в одном столбце не может быть двух ферзей. Вызов должен использовать col вместо col + 1 и каким-то образом учитывать, где мы остановились в текущем столбце.

  3. Чтобы разрешить столбцы без ферзей, безусловный вызов «решить (конфигурация, N, столбец + 1)» должен быть помещен где-то в функции решения.

  4. Когда мы разрешаем пункт 2, функция canPlace должна быть изменена, чтобы также проверять столбец.

  5. Циклы canPlace должны прерываться всякий раз, когда найдена пешка.

person Gassa    schedule 06.12.2014

Когда путь блокируют пешки, вы не должны просто переходить к следующему столбцу, потому что вы можете разместить больше ферзей в том же столбце. Вы должны изменить свой код, чтобы передавать и строку, и столбец при рекурсии, и переходить только к следующему квадрату, а не к следующему столбцу.

Кроме того, похоже, что ваш алгоритм находит первое решение, а не лучшее решение. Исходная задача о ферзях заботилась только об одном возможном решении, но с модифицированной задачей вам нужно убедиться, что вы проверили все решения и запомнили лучшее из них.

Кроме того, ваша функция canPlace неверна. Он вообще не учитывает пешки.

person JS1    schedule 06.12.2014