八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于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 | } |