八皇后问题

百度百科关于八皇后问题的说明:

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

废话不多说,直接贴代码:

#include "stdio.h"
#include "string.h"

// ----------------------------------------------------------------------------
//                 definition
// ----------------------------------------------------------------------------
#define QN_NUM              8
#define AREA_X_MAX          8
#define AREA_Y_MAX          8

// ---------------------------------------------------------------------------
//                 local type
// ----------------------------------------------------------------------------

// basic type
typedef unsigned char   BYTE;
typedef unsigned short  WORD;
typedef unsigned long   DWORD;

// BOOL
typedef enum
{
    FALSE = 0,
    TRUE
}BOOL;

// pos 
typedef struct
{
    BYTE by_x;
    BYTE by_y;
}T_Pos, *PT_Pos;

// queen
typedef struct 
{
    BYTE  by_sn;          // sn 
    T_Pos t_pos;          // pos
}T_QN, *PT_QN;

// area node
typedef struct 
{
    T_Pos t_pos;
    BOOL  b_active;
}T_AN, *PT_AN;


// ---------------------------------------------------------------------------
//                 func part
// ----------------------------------------------------------------------------

// ------------------------------------
// init queen and area
// ------------------------------------
void Set_Default_Val(PT_QN pt_qn, PT_AN pt_an)
{
    BYTE  by_i      = 0;
    BYTE  by_j      = 0;
    PT_AN pt_an_tmp = NULL;
    PT_QN pt_qn_tmp = NULL;

    // init area
    for(by_i=0 ; by_i<AREA_X_MAX ; by_i++)
    {
        for(by_j=0 ; by_j<AREA_Y_MAX ; by_j++)
        {
            pt_an_tmp = pt_an + by_i * AREA_Y_MAX + by_j;
            pt_an_tmp->b_active   = TRUE;
            pt_an_tmp->t_pos.by_x = by_i;
            pt_an_tmp->t_pos.by_y = by_j;
        }
    }

    // init queen
    for(by_i=0; by_i<QN_NUM ; by_i++)
    {
        pt_qn_tmp             = pt_qn + by_i;
        pt_qn_tmp->by_sn      = by_i;
        pt_qn_tmp->t_pos.by_x = 0;
        pt_qn_tmp->t_pos.by_y = 0;
    }
}

// ------------------------------------
// print qn
// ------------------------------------
void Print_QN(BYTE by_rslt_sn, PT_QN pt_qn)
{
    BYTE by_i, by_j;
    BYTE by_sn;
    BYTE aby_line[100];
    BYTE aby_qn[20];

    printf("\r\n - new rslt found - [%02d]\r\n", by_rslt_sn);

    printf("-------------------------\r\n");
    for(by_i=0 ; by_i<AREA_X_MAX ; by_i++)
    {
        for(by_sn=0 ; by_sn<QN_NUM ; by_sn++)
        {
            if(by_i == pt_qn[by_sn].t_pos.by_x)
            {
                memset(aby_line, 0x00, 100);
                memcpy(aby_line, "|  |  |  |  |  |  |  |  |", strlen("|  |  |  |  |  |  |  |  |"));    
                
                memset(aby_qn, 0x00, 20);
                sprintf(aby_qn, "Q%d", by_sn);
                by_j = 1 + strlen("  |") * (pt_qn[by_sn].t_pos.by_y);
                memcpy(&aby_line[by_j], aby_qn, strlen(aby_qn));
                
                printf("%s", aby_line);
            }
        }
        printf("\r\n-------------------------\r\n");
    }

}

// ------------------------------------
// disable area node
// ------------------------------------

/*
 * 斜线的斜率固定(1:1).
 * 区域建模在第一象限
 * y = x + b1 or y = -x + b2
 */
void Disable_Area_Node(const PT_QN pt_qn,
                             PT_AN pt_an)
{
    BYTE  by_i      = 0;
    BYTE  by_j      = 0;

    int   i_b1      = 0;
    int   i_b2      = 0;

    PT_AN pt_an_tmp = NULL;

    // calc b1 & b2
    i_b1 = pt_qn->t_pos.by_y - pt_qn->t_pos.by_x;    // (y - x)
    i_b2 = pt_qn->t_pos.by_y + pt_qn->t_pos.by_x;    // (y + x)

    for(by_i=0 ; by_i<AREA_X_MAX ; by_i++)
    {
        for(by_j=0 ; by_j<AREA_Y_MAX ; by_j++)
        {
            pt_an_tmp = pt_an + by_i * AREA_Y_MAX + by_j;
            // 排除横纵坐标
            if(  !(  (pt_qn->t_pos.by_x != by_i)
                   &&(pt_qn->t_pos.by_y != by_j)))
            {
                pt_an_tmp->b_active = FALSE;   
            }
            
            // 排除y= x + b
            if(pt_an_tmp->t_pos.by_y == (pt_an_tmp->t_pos.by_x + i_b1)) 
            {
                pt_an_tmp->b_active = FALSE;
            }
            
            // 排除y=-x + b
            if(pt_an_tmp->t_pos.by_y == (i_b2 - pt_an_tmp->t_pos.by_x)) 
            {
                pt_an_tmp->b_active = FALSE;
            }
        }
    }
}

// ------------------------------------
// search active node
// ------------------------------------
void Search_Active_Node_In_Row(const PT_AN pt_row_start, 
                               BYTE*       pby_num,
                               BYTE*       pby_buf)
{
    BYTE  by_i         = 0;
    BYTE  by_buf_index = 0;
    PT_AN pt_an_tmp    = NULL;

    *pby_num  = 0;
    pt_an_tmp = pt_row_start;
    
    for(by_i=0 ; by_i<AREA_X_MAX ; by_i++)
    {
        if(pt_an_tmp->b_active)
        {
            pby_buf[by_buf_index] = by_i;
            by_buf_index++;
            (*pby_num)++;
        }
        pt_an_tmp++;
    }
}

// ------------------------------------
// copy an
// ------------------------------------
void Copy_AN(PT_AN pt_an1, PT_AN pt_an2)
{
    BYTE  by_i;
    BYTE  by_j;

    PT_AN pt_an_temp1 = NULL;
    PT_AN pt_an_temp2 = NULL;

    for(by_i=0 ; by_i<AREA_X_MAX ; by_i++)
    {
        for(by_j=0 ; by_j<AREA_Y_MAX ; by_j++)
        {
            pt_an_temp1 = pt_an1 + by_i * AREA_Y_MAX + by_j;
            pt_an_temp2 = pt_an2 + by_i * AREA_Y_MAX + by_j;
            
            pt_an_temp1->b_active = pt_an_temp2->b_active;
            pt_an_temp1->t_pos    = pt_an_temp2->t_pos;
        }
    }
}


// ------------------------------------
// match queen in a single line
// ------------------------------------

/*
 * search direction:
 * row 0 ------>
 * row 1 ------>
 *  .
 *  .
 * row 7 ------>
 *
 */

void Match_In_Row(PT_AN pt_an,
                  PT_QN pt_qn,          // buffer for queen
                  BYTE  by_row_num, 
                  BYTE* pby_cur_rslt_num)
{   
    T_AN  at_an_tmp[AREA_X_MAX][AREA_Y_MAX];
    BYTE  aby_active_node_buf[AREA_Y_MAX];
    BYTE  by_active_node_num;
    BYTE  by_i;
    PT_AN pt_row_start = NULL;

    pt_row_start = pt_an + AREA_Y_MAX * by_row_num;
    Search_Active_Node_In_Row(pt_row_start, &by_active_node_num, aby_active_node_buf);

    for(by_i=0 ; by_i<by_active_node_num ; by_i++)
    {
        if(0 == by_row_num)
        {
            Set_Default_Val(pt_qn, pt_an);
        }
    
        pt_qn[by_row_num].t_pos.by_x = by_row_num;
        pt_qn[by_row_num].t_pos.by_y = aby_active_node_buf[by_i];
            
        // find a valid result
        if((AREA_X_MAX-1) == by_row_num)
        {
            Print_QN(*pby_cur_rslt_num, pt_qn);
            (*pby_cur_rslt_num)++;
        }
        else // search in next row
        {
            Copy_AN(&at_an_tmp[0][0], pt_an); 
            Disable_Area_Node(&pt_qn[by_row_num], &at_an_tmp[0][0]);
            Match_In_Row(&at_an_tmp[0][0], pt_qn, by_row_num+1, pby_cur_rslt_num);
        }
    }
}

// ------------------------------------
// main func
// ------------------------------------
void main()
{
   T_AN at_an[AREA_X_MAX][AREA_Y_MAX];
   T_QN at_qn[QN_NUM];
   BYTE by_rslt_num = 0;

   printf("Start...\r\n");

   Set_Default_Val(at_qn, &at_an[0][0]);
   Match_In_Row(&at_an[0][0],
                 at_qn,          
                 0, 
                &by_rslt_num);

   printf("done...\r\n");
   getchar();
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值