递归
分书问题
思路
(1) 定义一个整型的二维数组,将表中的阅读喜好用初始化方法赋给这个二维数组。可定义:
int like[5][5] = { {0,0,1,1,0}, {1,1,0,0,1}, {0,1,1,0,1}, {0,0,0,1,0}, {0,1,0,0,1} };
(2) 定义一个整型一维数组book[5],用来记录书是否已被选用。用下标作为5本书的编号,被选过元素值为1,未被选过元素值为0,初始化皆为0。
int book[5] = {0,0,0,0,0};
(3) 画出思路图。
① 定义试着给第i人分书的函数Try(i),i = 0,1,2,3,4。
② 试着给第i个人分书,先试分0号书,再分1号书,分2号书,……,因此有一个与结点,让j表示书,j=0,1,2,3,4。
③条件c是由两部分“与”起来的,“第i个人喜欢j书,且j书尚未被分走”。满足这个条件是i人能够得到j书的条件。
④ 如果不满足c条件,则什么也不做,这是直接可解结点。、
⑤ 满足c条件,做三件事:
第一件事:将j书分给i,用一个数组take[i]=j,记住书j给了i,同时记录j书已被选用,book[j]=1.
第二件事:查看i是否为4,如果不为4,表示尚未将所有5个人所要的书分完,这时应递归再试下一个人,即Try(i+1)。若果i==4,则应先使方案数n=n+1,然后输出第n个方案下的每个人所得之书。
第三件事:回溯。让第i人退回j书,恢复j书尚未被选的标志,即book[j]=0.这是在已输出第n个方案之后,去寻找下一个分书方案所必需的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <stdio.h>
int like[5][5] = { {0,0,1,1,0}, {1,1,0,0,1}, {0,1,1,0,1}, {0,0,0,1,0}, {0,1,0,0,1} }; int book[5] = {0,0,0,0,0}; int take[5] = {0}; int n = 0; void Try(int i){
int j,k;
for(j = 0 ; j < 5 ; j++){ if(like[i][j] == 1 && book[j] == 0){ take[i] = j; book[j] = 1; if(i == 4){ n++; printf("==========第%d个方案是==========\n",n); for(k = 0 ; k < 5 ; k++){ printf("第%d个人拿的第%d本书\n",k+1,take[k]+1); } } else{ Try(i+1); } book[j] = 0; } } }
int main(){ Try(0); }
|
八皇后问题
思路
将整个问题拆解成几个小问题,分步解决。
1.判断是否可以放下皇后棋子(同行同列同对角线上还没有棋子)
2.try函数用来实现递归和回溯
3.打印结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <stdio.h> #include <math.h>
int place[8] = {0}; int snum = 0; void showResult(); int canPlace(int i,int j); void try(int i);
void showResult(){ int i; printf("===第%d个方案\n",++snum); for( i = 0 ; i < 8 ; i++ ){ printf("第%d行的皇后放置在第%d列\n",i,place[i]); } } int canPlace(int i,int j){ int k; for(k = 0 ; k < 8 ; k++ ){ if(place[k] == j || abs(place[k] - j ) == abs(k - i)) return 0; } return 1; }
void try(int i){ int j; if(i == 7){ showResult(); return; } for(j = 0 ; j < 8 ; j++ ){ if(canPlace(i,j)){ place[i] = j; try(i+1); place[i] = 0; } } }
int main(){ try(0); return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include <stdio.h> #include <math.h>
int chessboard[8][8] = {0}; int snum = 0; int isDanger(int row,int col){ int i,j; for( i = 0 ; i < 8 ; i++ ){ if(chessboard[row][i] == 1) return 0; } for( i = 0 ; i < 8 ; i++ ){ if(chessboard[i][col] == 1) return 0; } for( i = 0 ; i < 8 ; i++ ){ for( j = 0 ; j < 8 ; j++ ){ if( chessboard[i][j] == 1 && abs(i-row) == abs(j-col) ) return 0; } } return 1; }
void printResult(){ int i,j; printf("====第%d个方案====\n",++snum); for( i = 0 ; i < 8 ; i++ ){ for( j = 0 ; j < 8 ; j++ ){ if( chessboard[i][j] == 1 ) printf("chessboard[%d][%d]\n",i,j); } } }
void eightQueen(int row) { int col; if( row > 7 ){ printResult(); return ; } for( col = 0 ; col < 8 ; col++ ){ if(isDanger(row,col)){ chessboard[row][col] = 1; eightQueen( row + 1 ); chessboard[row][col] = 0; } } }
int main(){
eightQueen(0); return 0;
}
|
背包问题
思路
每个物品有两种状态及放入和未放入。我们假设除最后一个以外的前面已经是最优解,再找出最后一个的最优解即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <stdio.h>
int weight[5] = {2,2,6,5,4}; int value[5] = {6,3,5,4,6};
int exp(int i,int j){ int value1,value2; int max = 0; if(weight[i] <= j && i != -1){ value1 = exp(i-1,j-weight[i]) + value[i]; value2 = exp(i-1,j); value1 > value2 ? (max = value1) : (max = value2); } return max; }
void main(){ int result; result = exp(4,10); printf("%d",result); }
|
回溯
素数环问题
用1~n共n个不重复整数构造一个环形结构,使相邻两个数之和为素数。
如下图是一个n=6的素数环。
思路
同样把问题拆解成几个负责不同功能的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| #include <stdio.h> #include <malloc.h> #include <string.h> #include <math.h>
int isPrime(int n) { int i,k; k = (int)sqrt(n); for(i=2;i<=k;i++) { if(n%i==0) return 0; } return 1; }
int canPlace(int *p,int i,int j,int n) { int k,flag; for(k=0;k<i;k++) { if(p[k]==j) return 0; } flag = isPrime(j+p[i-1]); if(flag==1 && i==n-1) { flag = isPrime(j+p[0]); } return flag; }
void showResult(int *p,int n) { int i; static count = 0; printf("****第%d个解****\n",++count); for(i=0;i<n;i++) { printf("%d ",p[i]); } printf("\n"); }
void primeCycle(int n) { int i=1,j,k; int *p = (int *)malloc(sizeof(int)*n); memset(p,0,n*sizeof(int)); p[0] = 1; while(i>=1) { for(j=p[i]+1;j<=n;j++) { if(canPlace(p,i,j,n)==1) { p[i] = j; break; } } if(j>n) { p[i--] = 0; } else if(i==n-1) { showResult(p,n); p[i--] = 0; } else i++; } free(p); printf("finished\n"); }
void main() { int n; printf("Input an integer\n"); scanf("%d",&n); primeCycle(n); }
|
待编辑…