八皇后问题一解--用几何方法简化编程问题

八皇后问题一解--用几何方法简化编程问题

在一个8×8国际象棋盘上,有8个皇后,每个皇后占一格;要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行、同一列或同一对角线上。问共有多少种不同的方法。
这是一个古老的问题,解法分很多种,串行,并行,递归,循环,等等
不过我认为这道题目的真正难点在于找到一个从坐标到该坐标是否与其queen冲突的映射。剩下的只是实现方法上的不同
一个Queen的攻击范围有8个方向,如果不考虑正负向,可认为其攻击方位实在4条直线上,OK
-在横向的冲突最容易解决,因为我们解题时一般都是逐行求解,所以不会出现两个Queen在一行上的情况
-在纵向上的冲突也容易解决,我们可以声明一个有个8个元素的BYTE数组BYTE col[8]={},如果坐标为(i,j)的位置上有Queen,则执行col[j]=1就可以了,以后直接判断对应列标志位是否为1就可以判端新Queen是否与已有的Queen存在冲突
-在正45度和负45度线上的冲突处理就比较复杂了,这里运用一个最简单的几何定理就可以简化问题,几何中直线的定义是y=ax+b;而我们的其余两种冲突相应的可表示为
y=x+b1和y=-x+b2;
然后根据x[0,7],和y[0,7]的取值区间得出相应b1,b2的取值区间为
b1 [-7,7]
b2 [0,14]
将b1区间平移7也得到了[0,14]
这样我们就可以再声明两个数组BYTE a[15],b[15],来唯一标识正45度和负45度线上的冲突了,映射关系为
i-j+7 ==>a[15];
i+j    ==>b[15];

一下是我实现的解法

 1 #include  " stdafx.h "
 2 void  Qu( int  line);
 3 BYTE col[ 8 ] = {} ; //
 4 BYTE a[ 15 ] = {} ; // 主对角线
 5 BYTE b[ 15 ] = {} ; // 辅对角线
 6 char  chessArr[ 8 ][ 8 ];
 7 int  MethodCnt = 0 ;
 8 void  CalQueeen()
 9 {
10    memset(chessArr[0],'*',64);
11    Qu(0);
12}

13 void  Qu( int  line)
14 {
15    if (line<8)
16    {
17        for (int c=0;c<8;c++)
18        {
19            if (col[c]==0 && a[line-c+7]==0 && b[line+c]==0)
20            {
21                chessArr[line][c]='@';
22                col[c]=1;
23                a[line-c+7]=1;
24                b[line+c]=1;
25                Qu(line+1);
26                chessArr[line][c]='*';//回溯
27                col[c]=0;
28                a[line-c+7]=0;
29                b[line+c]=0;
30            }

31        }

32    }

33    else//到达搜索顶点
34    {
35        MethodCnt++;
36        cout<<"_____________________________________________________________________"<<endl;
37        cout<<MethodCnt<<endl;
38        cout<<"---------------------------------------------------------------------"<<endl;
39        for(int i=0;i<8;i++)
40        {
41            for(int j=0;j<8;j++)
42                cout<<chessArr[i][j];
43            cout<<endl;
44        }

45    }

46}

最后一共得出92中解法,有兴趣的朋友可以试试

 

你可能感兴趣的:(八皇后问题一解--用几何方法简化编程问题)