Now is best !

回溯法

一、回溯法算法框架
回溯法是一种枚举状态空间中所有可能状态的系统方法,它是一个一般性的算法框架,应用时须具体问题具体分析。
 
在回溯法的每一步,我们从一个给定的部分解a=(a_1, a_2, ... , a_k)开始,尝试着在最后添加元素来扩展这个部分解。扩展之后,我们必须测试他是否为一个完整的解——如果是的话,需要输出这个解、更新解的计数器或者其他任何你想做的事。如果仍不完整,我们必须检查这个部分是否有可能扩展成完整解。如果有可能,递归下去;如果没有可能,从a中删除新加入的最后一个元素,然后尝试该位置上的其他可能性。
 
下面是代码,使用了一个全局的finished标志来允许提前终止回溯过程。
 
bool finished = FALSE;        // found all solutions yet? 
void backtrack(int a[], int k, data input)
{
    if (is_a_solution(a,k,input))
        process_solution(a,k,input);
    else {
        k = k+1;
        construct_candidates(a,k,input,c,&ncandidates);
        for(i=0; i<ncandidates; ++i) {
                a[k] = c[i];
                backtrack(a,k,input);
                if (finished)
                    return; 
        }
    }
}
 
is_a_solution用来测试向量a的前k个元素是否为一个完整的解,input参数用来给这个函数传递一些信息,例如目标解的长度。
construct_candidates根据a的前k-1个元素值,将第k个元素的所有候选值放到数组c中。候选值的个数为ncandidates。
process_solution可以用来输出解。
 
二、下面是两个用到上述框架的例子
1. 构造所有子集
 1 #include <stdio.h>
 2 #define NMAX 10
 3 #define MAXCANDIDATES 10
 4 
 5 int finished = 0;
 6 void output_solution(int *a, int k)
 7 {
 8     int i;
 9     printf("{");
10     for(i=1; i<=k; ++i) {
11         if (a[i] == 1)
12             printf(" %d", i);
13     }
14     printf("}\n");
15 }
16 void construct_candidates(int *a, int k,int *c, int *ncandidates)
17 {
18     c[0] = 1;
19     c[1] = 0;
20     *ncandidates = 2;
21 }
22 
23 void backtrack(int *a, int k, int n)
24 {
25     int ncandidates;
26     int c[MAXCANDIDATES];
27     int i;
28 
29     if (k == n) {
30         output_solution(a,k);
31     } else {
32         k = k + 1;
33         construct_candidates(a,k,c,&ncandidates);
34         for(i=0; i<ncandidates; ++i) {
35             a[k] = c[i];
36             backtrack(a,k,n);
37             if (finished)
38                 return;
39         }
40     }
41 }
42 
43 int main()
44 {
45     int a[NMAX];
46     backtrack(a,0,4);
47 }
subset.c

2. 八皇后

 1 #include <stdio.h>
 2 #define NMAX 20
 3 #define N 8
 4 int finished = 0;
 5 int solution_count = 0;
 6 void output_solution(int *a, int k)
 7 {
 8     int i;
 9     for(i=1; i<=k; ++i)
10         printf("%d ",a[i]);
11     printf("\n");
12 }
13 
14 
15 void construct_candidates(int *a, int k, int n, int *c, int *ncandidates)
16 {
17     //construct the kth candidate based on the previous k-1 candidates
18     int exist[NMAX];
19     int i,j,ok;
20     for(i=1; i<=n; ++i)
21         exist[i] = 0;
22     for(i=1; i<k; ++i)
23         exist[a[i]] = 1;
24 
25     *ncandidates  = 0;
26     for(i=1; i<=n; ++i) {
27         ok = 1;
28         for(j=1; j<k; ++j) {
29             if (a[j]-j == i-k || a[j]+j == i+k ) {
30                 ok = 0;
31             }
32             if (a[j] == i)
33                 ok = 0;
34         }
35         if (ok) {
36             c[*ncandidates] = i;
37             *ncandidates = *ncandidates+1;
38         }
39     }
40 }
41 
42 void backtrack(int *a, int k, int n)
43 {
44     int c[NMAX];
45     int i;
46     int ncandidates;
47 
48     if (k == n) {
49         output_solution(a,n);
50         solution_count++;
51     } else {
52         k = k + 1;
53         construct_candidates(a,k,n,c,&ncandidates);
54         for(i=0; i<ncandidates; ++i) {
55             a[k] = c[i];
56             backtrack(a,k,n);
57             if (finished)
58                 return;
59         }
60     }
61 }
62 
63 void queen(int n)
64 {
65     int a[NMAX];
66     backtrack(a,0,n);
67     printf("solution count = %d\n",solution_count);
68 }
69 int main()
70 {
71     queen(N);
72     return 0;
73 }
eight_queen.c

 

参考文献:<挑战编程程序设计竞赛训练手册 第八章>

posted on 2013-11-29 23:34  fang0703  阅读(357)  评论(0)    收藏  举报

导航