试探法也称为回溯法,它是一种系统地搜索问题解的方法,该算法设计思想适用范围相当广泛。试探法是搜索算法中的一种控制策略。它的基本思想是:从问题的某一种状态(一般是默认的初始状态)出发,搜索从这种状态出发所能达到的所有“状态”,当一条路走到“尽头”的时候,先退几步,接着从另一种可能的“状态”出发,继续搜索,直到所有的“路径”都尝试过。
对于常见的迷宫问题,就可使用试探法来求解,具体过程为:进入迷宫后,先随意选择一个前进方向,一步步向前试探前进,如果碰到死胡同,说明前进方向已无路可走,这时,首先看其他方向是否还有路可走,如果有路可走,则沿该方向再向前试探;如果已无路可走,则返回一步,再看其他方向是否还有路可走;如果有路可走,则沿该方向再向前试探。按此原则不断试探、回溯、再搜索,直到找到新的出路或从原路返回入口处无解为止。
一般性模板:
例题一、生成彩票号码组合
常见的彩票号码都是由一些数字组成的,生成彩票号码其实就是将所有数字进行不同的组合。例如,假设有一种彩票,每注由7个1~29的数字组成,且这7个数字不能相同,编写程序生成所有的号码组合。
很多人看到这题首先会想到写七层嵌套循环得出结果,但是代码会很烦琐,复杂度也高
但这题用回溯更有意思
首先我们知道有7个彩票号码各不相同,而取值是1~29,那么我们可以从第七个数(数组最末尾的6)开始,首先最外层是combine(29,7)到内层combine(28,6),…,combine(23, 1),然后输出,接着循环让数组最末尾的数字递减,依次类推,数组左边的数永远比右边大同时也不会重复,这样我们就可以得到需要的组合,但是时间复杂度太大,一时半会运行不完
详细C代码如下:
#include<stdio.h>
#define MAXN 7
#define NUM 29
int num[NUM];
int lottery[MAXN];
void combine(int n, int m){
int i, j;
for(i = n; i >= m; i--){
lottery[m - 1] = num[i - 1];
if(m > 1)
combine(i - 1, m - 1);
else{
for(j = MAXN - 1; j >= 0; j--){
printf("%3d", lottery[j]);
}
getch();
printf("\n");
}
}
}
int main(){
int i, j;
for(i = 0; i < NUM; i++){
num[i] = i + 1;
}
for(i = 0; i < MAXN; i++)
lottery[i] = 0;
combine(NUM, MAXN);
getch();
return 0;
}
部分运行结果如下: