八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:
在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
思路:
- 一维数组array存放皇后位置,array[i]=j 表示i行j列有一个皇后。
- 判断该位置放置皇后是否合法。
- 该位置合法,则进行下一行放置。
- 该位置非法则列值j++,进行第2步的判断。
- 当放满8个皇后(即i从0–>7)时,找到结果+1。
- 当某行中的列值(即array[i])>=8时,说明该行在前面行的摆放情况下无解。
- 则回退到上一行,对上一行的列值j++,进行2步判断。
- 当row回退到第一行(i=0),且第一行的列值超出范围(array[0]>=8)时,代表搜索结束。
- 输出所有可行解。
1 |
|
2 |
|
3 | |
4 |
|
5 | |
6 | int check(int *q, int row) |
7 | { |
8 | if(row == 0) |
9 | { |
10 | return 1; |
11 | } |
12 | else |
13 | { |
14 | int y; |
15 | int x0 = q[row]; /* row行的列值 */ |
16 | for(y = 0; y < row; y++) |
17 | { |
18 | int x = q[y]; /* 前row行每列的值 */ |
19 | if(x == x0) /* 列值不能相同 */ |
20 | return 0; |
21 | else if(x - x0 == row - y) /* 对角线方向1 */ |
22 | return 0; |
23 | else if(x0 - x == row - y) /* 对角线方向2 */ |
24 | return 0; |
25 | } |
26 | } |
27 | return 1; |
28 | } |
29 | |
30 | int queen() |
31 | { |
32 | /**************************************** |
33 | q[N]记录各行可行的摆放位置。下标是行坐标, |
34 | 对应下标存储的值是可行解的列坐标。 |
35 | *****************************************/ |
36 | int q[N] = {0}; |
37 | int found = 0; /* 记录可行解的个数 */ |
38 | int row = 0; /* 行 */ |
39 | int done = 0; |
40 | |
41 | while(done == 0) |
42 | { |
43 | if(check(q, row)) |
44 | { |
45 | if(row == N-1) /* 所有位置都可行后,得到一个解 */ |
46 | { |
47 | found++; |
48 | } |
49 | else |
50 | { |
51 | row++; /* 新一行 */ |
52 | q[row] = 0; |
53 | continue; |
54 | } |
55 | } |
56 | q[row] += 1; /* 列值+1 */ |
57 | while(q[row] >= N) /* 当前行的列超出范围时 */ |
58 | { |
59 | row--; /* 上一行 */ |
60 | if(row >= 0) |
61 | { |
62 | q[row]++; /* 对应行的列值+1 */ |
63 | } |
64 | else /* row < 0寻找结束 */ |
65 | { |
66 | done = 1; |
67 | break; |
68 | } |
69 | } |
70 | } |
71 | return found; |
72 | } |
73 | |
74 | int main() |
75 | { |
76 | int found; |
77 | found = queen(); |
78 | printf("found = %d\n",found); |
79 | return 0; |
80 | } |
递归版本:
1 | int search(int *array, int row) |
2 | { |
3 | int count = 0; |
4 | int i; |
5 | for(i = 0; i < N; i++) |
6 | { |
7 | array[row] = i; |
8 | if(check(array, row)) |
9 | { |
10 | if(row == N - 1) |
11 | { |
12 | count++; |
13 | } |
14 | else |
15 | { |
16 | count += search(array, row + 1); |
17 | } |
18 | } |
19 | } |
20 | return count; |
21 | } |
22 | |
23 | int queen() |
24 | { |
25 | int array[N] = {0}; |
26 | return search(array, 0); |
27 | } |