回溯法
回溯(backtracking)法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题.
例题
写一个在1,2,…,9(顺序不能变)数字之间插入+或-或什么都不插入,使得计算结果总是100的程序,并输出所有的可能性。
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
| #include <stdio.h> #define N 9 void fun(char op[],int sum,int prevadd,int a[],int i) { if (i==N) { if (sum==100) { printf(" %d",a[0]); for (int j=1;j<N;j++) { if (op[j]!=' ') printf("%c",op[j]); printf("%d",a[j]); } printf("=100\n"); } return; } op[i]='+'; sum+=a[i]; fun(op,sum,a[i],a,i+1); sum-=a[i];
op[i]='-'; sum-=a[i]; fun(op,sum,-a[i],a,i+1); sum+=a[i];
op[i]=' '; sum-=prevadd; int tmp; if (prevadd>0) tmp=prevadd*10+a[i]; else tmp=prevadd*10-a[i]; sum+=tmp; fun(op,sum,tmp,a,i+1); sum-=tmp; sum+=prevadd; } int main() { int a[N]; char op[N]; for (int i=0;i<N;i++) a[i]=i+1; printf("求解结果\n"); fun(op,a[0],a[0],a,1); }
|