八皇后問題一解--用幾何方法簡化編程問題
在一個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
}

2

3



4



5



6

7

8

9



10

11

12

13

14



15

16



17

18



19

20



21

22

23

24

25

26

27

28

29

30

31

32

33

34



35

36

37

38

39

40



41

42

43

44

45

46

最后一共得出92中解法,有興趣的朋友可以試試
posted on 2009-08-10 15:11 pear_li 閱讀(1920) 評論(0) 編輯 收藏 引用 所屬分類: C++