欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

每日算法练习——递归(八皇后问题:EightQueen)

程序员文章站 2022-05-25 11:43:17
...

知识补充:

八皇后问题

八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

摘自wiki百科:https://zh.wikipedia.org/wiki/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98

每日算法练习——递归(八皇后问题:EightQueen)

C语言代码实现:

#include <stdio.h>
#include <stdlib.h>

int count =0; // 计数

// 判断危险 
int notDanger(int row, int j , int (*chess)[8] )
{
    int i,k,flag=1;

    // 判断列方向,
    for(i=0; i<8; i++)
    {
        if(i!=row)  //非本皇后(棋子)的位置
        {
            if(*(*(chess+i)+j)!=0)
            {
                flag = 0;
                return flag;
            }
        }
    }
    // 因为是按行放棋子,每行最多一个棋子,所以不需要判断行方向

    // 左上方向
    for(i=row-1,k=j-1; i>=0&&k>=0; i--,k--)
    {
        if(*(*(chess+i)+k)!=0)
        {
            flag = 0;
            return flag;
        }
    }
    // 右下方向
    for(i=row+1,k=j+1; i<8&&k<8; i++,k++)
    {
        if(*(*(chess+i)+k)!=0)
        {
            flag = 0;
            return flag;
        }
    }
    // 右上方向
    for(i=row-1,k=j+1; i>=0&&k<8; i--,k++)
    {
        if(*(*(chess+i)+k)!=0)
        {
            flag = 0;
            return flag;
        }
    }
    // 左下方向
    for(i=row+1,k=j-1; i<8&&k>=0; i++,k--)
    {
        if(*(*(chess+i)+k)!=0)
        {
            flag = 0;
            return flag;
        }
    }

    // 如果上述几个危险检查都通过了返回flag=1
    return flag;
}
// 参数 : 第row行 共n列,
void EightQueen(int row, int n,int (*chess)[8])
{
    int chess2[8][8],i,j;
    for(i=0; i<8; i++)
    {
        for(j=0; j<8; j++)
        {
            chess2[i][j] = chess[i][j];
        }
    }

    if( row == 8 )
    {
        printf("第 %d 种\n",++count);
        for(i=0; i<8; i++)
        {
            for(j=0; j<8; j++)
            {
                printf("%d ",*(*(chess2+i)+j));
            }
            printf("\n");
        }
    }
    else
    {
        for(j=0; j<n; j++)
        {

            if(notDanger(row, j, chess)) //判断第row行第j列的位置是否危险
            {
                for(i=0;i<8;i++)    // 如果不危险,先整行置0,再将第j列的位置置1;
                {
                    *(*(chess2+row)+i) = 0;
                }
                *(*(chess2+row)+j) = 1;
                EightQueen(row+1, n, chess2);
            }

        }
    }

}

int main()
{
    int chess[8][8],i,j;
    for(i=0;i<8;i++)
    {
        for(j=0;j<8;j++)
        {
            chess[i][j]=0;
        }
    }
    // 按行放棋子,从第0行开始
    EightQueen(0,8,chess);

    printf("总共有 %d 种解决方法!!\n",count);
    return 0;
}

 

wiki百科代码C语言:

简直妙的不行:

#include <stdio.h>

#define QUEENS       8 /*皇后数量*/
#define IS_OUTPUT    1 /*(IS_OUTPUT=0 or 1),Output用于选择是否输出具体解,为1输出,为0不输出*/

int A[QUEENS], B[QUEENS * 3 + 1], C[QUEENS * 3 + 1], k[QUEENS + 1][QUEENS + 1];
int inc, *a = &A[QUEENS], *b = &B[QUEENS], *c = &C[QUEENS];
void lay(int i)
{
    int j = 0, t, u;

    while (++j <= QUEENS)
        if (a[j] + b[j - i] + c[j + i] == 0)
        {
            k[i][j] = a[j] = b[j - i] = c[j + i] = 1;
            if (i < QUEENS)
                lay(i + 1);
            else
            {
                ++inc;
                if (IS_OUTPUT)
                {
                    for (printf("(%d)\n", inc), u = QUEENS + 1; --u; printf("\n"))
                        for (t = QUEENS + 1; --t; )
                            k[t][u] ? printf("Q ") : printf("+ ");
                    printf("\n\n\n");
                }
            }
            a[j] = b[j - i] = c[j + i] = k[i][j] = 0;
        }
}

int main(void)
{
    lay(1);
    printf("%d皇后共计%d个解", QUEENS, inc);
    getchar();
    return 0;
}