回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术称为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
例题:排列组合问题,找出n个自然数(1,2,3,4,。。。n)中取r个数的组合。
分析:当n=5,r=3,所有组合为:
5 4 3
5 4 2
5 4 1
5 3 2
5 3 1
5 2 1
4 3 2
4 3 1
4 2 1
3 2 1
将自然数排列在数组A中,排列时从A[1]>A[2]>A[3],后一个至少比前一个数小1,并且满足ri+A[ri]>r。例如,当n=5,r=3时,ri取1,则A[ri]必须大于2,即第一位只能是5、4、3中的一个。若ri+A[ri]<=r就要回溯,该关系就是回溯条件。为直观起见,当输出一组组合数后,若最后一位为1,也应作为一次回溯。
程序例子:
#include<stdio.h>
#define N 5
#define R 3
void main()
{
int a[R+1],ri,j;
ri=1;a[1]=N;
do{
if(ri!=R) //判断是否搜索到底
if(ri+a[ri]>R){ //判断是否回溯
a[ri+1]=a[ri]-1;
ri=ri+1;
}
else{
ri=ri-1; //回溯
a[ri]=a[ri]-1;
}
else{
for(j=1;j<=R;j++)
printf("%3d",a[j]);
printf("\n");
if(a[R]==1){ //判断是否回溯
ri=ri-1; //回溯
a[ri]=a[ri]-1;
}
else
a[ri]=a[ri]-1; //递推到下一个数
}
}while(a[1]!=R-1);
}