码迷,mamicode.com
首页 > 其他好文 > 详细

八皇后

时间:2015-03-20 01:35:43      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:国际象棋   include   数学家   count   queen   

八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。

该问题是19世纪著名的数学家高斯1850年提出:在8×8格的

国际象棋上摆放8个皇后,使其不能相互共计,即任意两个皇后

都不能处于同一行、同一列或同一斜线上,问有多少种摆法?

#include <stdio.h>
#define N 8
int count = 0;                      //答案编号
int queen[N];                       //第i(0<=i<N)行的皇后在queen[i]列                       
int col[N];                         //第i列是否可以放queen,可以为1,否则为0
int lu_to_rd[2*N];                  //左上(leftup)至右下(rightdown)的斜线上是否可以放queen,可以为1,否则为0
int ld_to_ru[2*N];                  //左下(leftdown)至右上是否可以放queen,可以为1,否则为0
void printArray();                  //打印答案
int able(int i,int j);              //第i行第j列是否是否可以放queen,可以返回1,否则返回0
void  recursion(int i);             //从第i行开始递归求解
int main(void)
{
    int i;
    for(i=0;i<N;i++)               //初始化
    {
         col[i] = 1;
    }
    for(i=0;i<2*N;i++)
    {
        lu_to_rd[i] = ld_to_ru[i] = 1;
    }
    recursion(0);
    return 0;
}

void printArray()
{
    int i,j;
    printf("----------------------------------\n");
    printf("count: %d \n",count++);
    for(i=0;i<N;i++)
    {
        for(j=0;j<8;j++)
        {
            if(queen[i]!=j)
            {
                printf("_");
            }
            else
            {
                printf("Q");                                           //打印queen
            }
            

        }

        printf("\n");
    }
    printf("----------------------------------\n");
}

int able(int i,int j)
{
    if (col[j] == 1 && lu_to_rd[i+j] == 1 && ld_to_ru[i-j-1+N] == 1)   //假如列方向和两个对角线方向上全都可以放queen,
    {                                                                  //就返回1
        return 1;
    }
    return 0;
}

void  recursion(int a)
{
    int i;
    if(a>=N)                                                    //a >= N 说明已经递归到最后一行,输出答案
    {
        printArray();
        
    }
    else
    {
        for(i=0;i<N;i++)                                      
        {
            if(able(a,i))
            {
                queen[a] = i;                                 //第i列可以放queen
                col[i] = 0;                                   //因为第i列已经放了queen,则要设置该列和两个对角线方向上为0      
                lu_to_rd[a+i] = ld_to_ru[a-i-1+N] = 0;
                
                recursion(a+1);                               //递归到下一行求解
                
                
                col[i] = 1;                                  //上一层递归结束后要更新第i列的信息
                lu_to_rd[a+i] = ld_to_ru[a-i-1+N] = 1 ;
            }
        }
    }
}

关于两条斜线上的问题:
一、判断问题
其实判断两个点在不在同一条斜线上,就是判断这两个点是不是属于同一条直线;
利用坐标的思想(x + y = b || x - y = c  #两条斜线的倾斜角为45度或135度);
而第i行第j列很容易转换成坐标;例如queen[1] = 2,queen[2] = 1,易得出这两点在同一条斜线上;
二、数组大小问题
8*8的正方形(0,0)(1,0)(0,1).........
会发现由整数点所连起来的倾角为45度的直线一共有13条,但为了判断的方便,我们把(7,0)(0,7)的点也算上;
这样就一共是15条,写简单点就写成了2*N;

本文出自 “一二三四五六七” 博客,请务必保留此出处http://8997342.blog.51cto.com/8987342/1622375

八皇后

标签:国际象棋   include   数学家   count   queen   

原文地址:http://8997342.blog.51cto.com/8987342/1622375

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!