八皇后问题

1 问题

    八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。

2 分析

    采用回溯算法,从上至下依次在每一行放置皇后,进行搜索,若在某一行的任意一列放置皇后均不能满足要求,则不再向下搜索,而进行回溯,回溯至有其他列可放置皇后的一行,再向下搜索,直到搜索至最后一行,找到可行解,输出。

3 实现

#include <stdio.h>

#define TRUE  1
#define FALSE 0

int sum = 0;           /*统计解法总数*/
int chsbrd[8][8] = {0};/*八皇后棋盘,初始化为0,未放置皇后*/

/*棋盘前row-1行已经放置了皇后,检查第row行,第colum列放置皇后是否可行*/
int pos_check(int row, int colum)
{
    int i,j;

    /*首行放置总是可行的*/
    if (row == 0)
    {
        return TRUE;
    }

    /*判断纵向是否可行*/    
    for (i = 0; i < row; i++)
    {
        if (chsbrd[i][colum] == 1)
        {
            return FALSE;
        }
    }

    /*判断从左上至右下的斜线是否可行*/
    i = row - 1;
    j = colum - 1;
    while (i >= 0 && j >= 0)
    {
        if (chsbrd[i][j] == 1)
        {
            return FALSE;
        }
        i--;
        j--;
    }
    /*判断从右上至左下的斜线是否可行*/
    i = row - 1;
    j = colum + 1;
    while (i >= 0 && j < 8)
    {
        if (chsbrd[i][j] == 1)
        {
            return FALSE;
        }
        i--;
        j++;
    }

    return TRUE;
}


void print_queen()
{
    int i,j;

    printf("第%d种解法: \n", ++sum);
    for (i = 0; i < 8; i++)
    {
        for (j = 0; j < 8; j++)
        {
            printf("%-2d", chsbrd[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

/*在row行上放置皇后,row的返回为[0,7]*/
void put_queen(int row)
{
    int j;

    /*在第row行的各列放置皇后*/
    for (j = 0; j < 8; j++)
    {
        chsbrd[row][j] = 1;
        if (pos_check(row, j) == TRUE)
        {
            if (row == 7)
            {
                print_queen();
            }
            else
            {
                put_queen(row+1);
            }
        }
        chsbrd[row][j] = 0;/*回溯*/
    }
}

int main()
{
    put_queen(0);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值