8皇后拼图与递归深度搜索

时间:2016-05-23 16:16:37

标签: c search recursion puzzle

我正在尝试解决C中的8皇后拼图问题。我遇到了递归搜索问题。该程序应该从给定的列开始:

 execute(tabuleiro,8,0);

其中8是电路板中的列数,0是起始列。

当我从第0列开始时,这是有效的。当我向递归搜索发送任何其他列号时,程序只计入最后一列。例如,如果我选择从数字5列开始搜索,则从第5列到第7列搜索代码,之后它应该从0到4搜索,但它不会这样做。

如果我这样做:

execute(tabuleiro,8,3);

它只填充最后5个colummns,并且不会返回到第0列来完成解决方案:

enter image description here

另外,如何在此代码中选择女王的初始位置?就像我之前说过的那样,列是在代码中分配的,但我不确定如何选择正确的列。

代码有3个功能:一个用于显示板,另一个用于检查移动是否合法(因此一个女王不会攻击另一个),最后一个用于放置一个女王并重复其余董事会。

#include <stdlib.h>
#include <windows.h>
int sol = 0;
void viewtab(int tab[][8], int N)
{
    int i,j;
    for( i = 0; i < N; i++)
    {
        for( j = 0; j < N; j++)
        {

            if(tab[i][j] == 1)
                printf("R\t");
            else
                printf("-\t");
        }
        printf("\n\n");
    }
    printf("\n\n");
    system("pause");
    printf("\n");
}
int secury(int tab[][8], int N, int lin, int col)
{
    // this function is to check if the move is secury
    int i, j;

    // attack in line
    for(i = 0; i < N; i++)
    {
        if(tab[lin][i] == 1)
            return 0;
    }

    //attack in colune
    for(i = 0; i < N; i++)
    {
        if(tab[i][col] == 1)
            return 0;
    }

    // attack in main diagonal
    //
    for(i = lin, j = col; i >= 0 && j >= 0; i--, j--)
    {
        if(tab[i][j] == 1)
            return 0;
    }
    for(i = lin, j = col; i < N && j < N; i++, j++)
    {
        if(tab[i][j] == 1)
            return 0;
    }

    // attack in main secondary

    for(i = lin, j = col; i >= 0 && j < N; i--, j++)
    {
        if(tab[i][j] == 1)
            return 0;
    }
    for(i = lin, j = col; i < N && j >= 0; i++, j--)
    {
        if(tab[i][j] == 1)
            return 0;
    }

    // if arrive here the move is secury and return true
    return 1;
}
void execute(int tab[][8], int N, int col)
{
    int i;
    if(col == N)
    {
        printf("Solution %d ::\n\n", sol + 1);
        viewtab(tab, N);
        sol++;
        return;
    }

    for( i = 0; i < N; i++)
    {
        // check if is secury to put the queen at that colune
        if(secury(tab, N, i, col))
        {
            // insert the queen (with 1)
            tab[i][col] = 1;

            // call recursive
            execute(tab, N, col + 1);

            // remove queen (backtracking)
            tab[i][col] = 0;
        }
    }
}
int main()
{
    int i, j, tabuleiro[8][8];
    for (i = 0; i < 8; i = i + 1)
        for (j = 0; j < 8; j = j + 1) tabuleiro[i][j] = 0;

    execute(tabuleiro,8,0);

    return 0;
}

2 个答案:

答案 0 :(得分:1)

搜索总是在最右边的列中停止,因为你专门告诉它停在那里:

void execute(int tab[][8], int N, int col)
{
    int i;
    if(col == N)
    {
        printf("Solution %d ::\n\n", sol + 1);
        viewtab(tab, N);
        sol++;
        return;
    }

查看您的终止条件:您根据最高列号检查当前列,然后停在那里。

如果要返回第0列,则必须更改循环逻辑。例如,让 col 达到N,此时将其重置为0,然后让它继续,直到达到原始值。另一种方法是继续,直到放置的皇后计数为N.

您以相同的方式选择初始点:您选择第一个并进行递归调用。如果最终导致解决方案,则打印它。如果没有,你的最高呼叫将继续到电路板的下一行(线路)并将第一个女王放在那里。

这已经在您的主要逻辑中。当电路板为空时,确保 secury 将返回 true ,而不是 false 或抛出错误。

答案 1 :(得分:-1)

一个。你可以把第一个女王放在(0,0)。 B.并从(0,0)开始搜索。 C.我认为没有必要开始寻找其他指数。 成功!!