递归

分治思想:当一个问题的规模较大且不易求解的时候,可以考虑将问题分成几个小模块,逐一的解决;

    因为分治思想处理问题,各小模块通常具有与大问题相同的结构,这种特性也使递归技术有发展方向

回溯

  回溯:形象的所就是一条路走到黑,当碰壁(无法进行)的时候在返回走另一种选择;

  (探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

八皇后问题

  问题描述:在 8*8 的国际棋盘上,摆放八个皇后,使其不能相互攻击;(任意两个两个都不能处于同行,同列,同斜线)问:有多少种摆法?

  方法:假设在第一行找一安全位置存放;在第二行同样的方法找一安全位置存放;... 直到第八行也存放了皇后。

回溯实现

 1 #include <stdio.h>
 2 #define DIM 8
 3 
 4 int is_a_solution(int a[DIM][DIM],int row);
 5 //void construct_candidates(int a[],int k,data input, int c[],int *ncandidates);
 6 void process_solution(int a[DIM][DIM]);
 7 //void make_move(int a[],int k, data input);
 8 //void unmake_move(int a[],int k,data inupt);
 9 
10 static int finished = 0;
11 static count = 0;
12 
13 int is_a_solution(int chess[DIM][DIM],int row)
14 {
15     return (row == DIM);
16 }
17 
18 void process_solution(int chess[DIM][DIM])
19 {
20     int i,j;
21     count++;
22     for(i=0;i<DIM;i++) {
23         for(j=0;j<DIM;j++)
24             printf("%d ",chess[i][j]);
25         printf("\n");
26     }
27     printf("\n");
28 }
29 
30 int is_collision(int chess[DIM][DIM],int x,int y)
31 {
32     int i,j;
33     for(i=x-1,j=y-1;i>=0 && j>=0;i--,j--)
34         if(chess[i][j] == 1)
35             return 1;
36 
37     for(i=x-1,j=y+1;i>=0 && j<DIM;i--,j++)
38         if(chess[i][j] == 1)
39             return 1;
40 
41     return 0;
42 }
43 
44 backtrack(int chess[DIM][DIM],int row, int* candidates)
45 {
46     if(is_a_solution(chess,row))
47         process_solution(chess);
48     else {
49         int i;
50         //construct_candidates(a,k,input,c,&ncandidates);
51         for(i=0;i<DIM;i++) {
52             if(candidates[i] || is_collision(chess,row,i))
53                 continue;
54             //make_move(a,k,input);
55             chess[row][i] = 1;
56             candidates[i] = 1;
57 
58             backtrack(chess,row+1,candidates);
59 
60             //unmake_move(a,k,input);
61             chess[row][i] = 0;
62             candidates[i] = 0;
63         }
64     }
65 }
66 
67 void generate_8queen(int chess[8][8])
68 {
69     int candidates[DIM] = {0,0,0,0,0,0,0,0};
70     backtrack(chess,0,candidates);
71     printf("total:%d\n",count);
72     return ;
73 }
74 
75 int main()
76 {
77     int chess[8][8] = {
78         {0,0,0,0,0,0,0,0},
79         {0,0,0,0,0,0,0,0},
80         {0,0,0,0,0,0,0,0},
81         {0,0,0,0,0,0,0,0},
82         {0,0,0,0,0,0,0,0},
83         {0,0,0,0,0,0,0,0},
84         {0,0,0,0,0,0,0,0},
85         {0,0,0,0,0,0,0,0}
86     };
87     generate_8queen(chess);
88 }

递归实现

 1 #include <stdio.h>
 2 int count = 0;
 3 
 4 int noDanger(int row,int j,int (*chess)[8]){
 5     int i,k,flag1=0;
 6     //判断列方向
 7     for(i=0;i<8;i++){
 8         if(*(*(chess+i)+j) != 0){
 9             return 0;
10         }
11     }
12     //判断左上方
13     for(i=row,k=j;i>=0 && k>=0;i--,k--){
14         if(*(*(chess+i)+k) != 0){
15             return 0;
16         }
17     }
18     //判断右下方
19     for(i=row,k=j;i<8 && k<8;i++,k++){
20         if(*(*(chess+i)+k) != 0){
21             return 0;
22         }
23     }
24     //判断左下方
25     for(i=row,k=j;i<8 && k>=0;i++,k--){
26         if(*(*(chess+i)+k) != 0){
27             return 0;
28         }
29     }
30     //判断右上方
31     for(i=row,k=j;i>=0 && k<8;i--,k++){
32         if(*(*(chess+i)+k) != 0){
33             return 0;
34         }
35     }
36     return 1;
37 }
38 
39 //参数row: 起始行
40 //参数n: 列数
41 //参数(*chess)[8]: (数组指针,指向长度为8数组)指向棋盘每一行的指针;
42 void EightQueen(int row,int n,int (*chess)[8]){
43     int chess2[8][8],i,j;
44     for(i=0;i<8;i++){
45         for(j=0;j<8;j++){
46             chess2[i][j]=chess[i][j];
47         }
48     }
49     if(8==row){
50         printf("第 %d 种\n",count);
51         for(i=0;i<8;i++){
52             for(j=0;j<8;j++){
53                 printf("%d ",*(*(chess2+i)+j));
54             }
55             printf("\n");
56         }
57         printf("\n");
58         count++;
59     }
60     else{
61         for(j=0;j<n;j++){//在这一行找全部安全位置,并以这个位置进入下一行递归
62             if(noDanger(row,j,chess)){//判断是否安全
63                 for(i=0;i<n;i++){//覆盖该行上一次找到的安全位置为0,保证下一次递归正常运行
64                     *(*(chess2+row)+i)=0;
65                 }
66                 *(*(chess2+row)+j)=1;
67 
68                 EightQueen(row+1,n,chess2);
69             }
70         }
71     }
72 }
73 
74 void main(){
75     int chess[8][8],i,j;
76     for(i=0;i<8;i++){
77         for(j=0;j<8;j++){
78             chess[i][j]=0;
79         }
80     }
81 
82     EightQueen(0,8,chess);
83     printf("共有 %d 种解决方法\n",count);
84 }