递归
分治思想:当一个问题的规模较大且不易求解的时候,可以考虑将问题分成几个小模块,逐一的解决;
因为分治思想处理问题,各小模块通常具有与大问题相同的结构,这种特性也使递归技术有发展方向
回溯
回溯:形象的所就是一条路走到黑,当碰壁(无法进行)的时候在返回走另一种选择;
(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
八皇后问题
问题描述:在 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 }
浙公网安备 33010602011771号