从N-皇后问题看回溯法

来源:互联网 发布:zookeeper 集群 端口 编辑:程序博客网 时间:2024/04/29 16:27

 使用递归:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <stddef.h>
 5
 6 int c = 0;
 7
 8 int print_queens(int *queens, int n)
 9 {
10     int i, j;
11
12     for (i = 0; i < n; i++)
13     {
14         for (j = 0; j < queens[i]; j++)
15         {
16             printf("-");
17         }
18         printf("*");
19         
20         for(j++; j < n; j++)
21         {
22             printf("-");
23         }
24         printf("/n");
25     }
26     return 0;
27 }
28
29 int check_position(int *queens, int row)
30 {
31     int i;
32
33     for (i = 0; i < row; i++)
34     {
35         if (queens[i] == queens[row] ||
36             abs(queens[row] - queens[i]) == abs(row - i))
37         {
38             return -1;
39         }
40     }
41     return 0;
42 }
43
44 int queens_solution(int *queens, int row, int n)
45 {
46     int col;
47
48     if (row >= n)
49     {
50         print_queens(queens, n);
51         //printf("%d./n", ++c);
52     }
53     else
54     {
55         for (col = 0; col < n; col++)
56         {
57             queens[row] = col;
58             if (check_position(queens, row) == 0) //check success
59             {
60                 queens_solution(queens, row+1, n); //try next row
61             }
62         }
63     }
64     
65     return 0;
66 }
67
68 int main()
69 {
70     int queens[] = {-1, -1, -1, -1, -1, -1, -1, -1};
71     queens_solution(queens, 0, 8);
72     printf("There is %d answers for the %d queen question", c, sizeof(queens) / sizeof(int));
73     getchar();
74     return 0;
75 }

76

 

如果不使用递归,则需要自己模拟出一个压栈和出栈的过程:

只需要做出如下修改即可:

 1 #include <stdio.h>
 2
 3 #define N 4 /* 定义棋盘大小 */
 4
 5 static int sum; /* 当前已找到解的个数 */
 6
 7 static int x[N]; /* 记录皇后的位置,x[i]=j表示皇后放在棋盘的第i行的第j列 */
 8
 9
10 /* 确定某一位置皇后放置与否,放置则返回1,反之返回0 */
11 int place(int k)
12 {
13     int j;
14     /* 测试皇后k在第k行第x[k]列时是否与前面已放置好的皇后相攻击. x[j] == */
15     /* x[k] 时,两皇后在同一列上;abs(k - j) == abs(x[j] - x[k]) 时,两皇 */
16     /* 后在同一斜线上。两种情况两皇后都可相互攻击,故返回0表示不符合条件。*/
17     for (j = 0; j < k; j ++)
18         if (x[j] == x[k] || abs(j - k) == abs(x[j] - x[k])) return 0;
19
20     return 1;
21 }
22
23 /* 打印棋局 */ 
24 void chessboard()
25 {
26     int i,j;
27      printf("第%d种解法:/n", ++ sum);
28      for (i = 0; i < N; i ++) {
29          for (j = 0; j < N; j ++)
30              if (j == x[i]) printf("Q ");
31              else printf("* ");
32          printf("/n");
33      }
34      printf("/n");
35 }
36
37 /* 回溯搜索解空间 */
38 void backtrack()
39 {
40     int k = 0;
41
42     x[0] = -1;
43     while (k >= 0) {
44         x[k] += 1; /* 向右移一列 */
45         /* 向右移至出最右列或可以放置皇后的列 */
46         while ((x[k] < N) && !(place(k))) x[k] += 1;
47         if (x[k] < N) /* 向右移未移出棋盘 */
48             if (k == N - 1) chessboard(); /* 已移至最后一行 */
49             else x[++ k] = -1; /* 向下移一行 */
50         else k --; /* 回溯到上一行 */
51     }
52 }
53
54
55
56 int main(void)
57 {
58     backtrack();
59     getch();
60     return 0;
61 }
62


原创粉丝点击