一、试探法算法的思想
试探法也叫回溯法,试探法的处事方式比较委婉,它先暂时放弃关于问题规模大小的限制,并将问题的候选解按某种顺序逐一进行枚举和检验。使用试探法的步骤如下:
(1)针对所给问题,定义问题的解空间。(2)确定易于搜索的解空间结构。(3)以深度优先方式搜索空间,并在搜索过程中用剪枝函数避免无效搜索。
二、实例演练
(1)“八皇后”问题
代码实现:
#include "stdio.h" #define N 8 int place(int row, int col); void backtrack(int row); void queens(); int solution[N], j, k, count, sols; int main() { queens(); printf("总共方案:%d\n", sols); system("pause"); return 0; } int place(int row, int col) { for (j = 0; j < row;j++) { if (row - j == solution[row]-solution[j]||row+solution[row]==j+solution[j]||solution[j]==solution[row]) { return 0; } } return 1; } void backtrack(int row) { count++; if (N==row) { sols++; for (k = 0; k < N;k++) { printf("%d\t", solution[k]); } printf("\n"); } else { int i; for (i = 0; i < N;i++) { solution[row] = i; if (place(row,i)) { backtrack(row + 1); } } } } void queens() { backtrack(0); }
实现结果:
(2)“29选7彩票组合”问题
代码实现:
#include "stdio.h" #define MAXN 7 //设置每一注彩票的位数 #define NUM 29 //设置组成彩票的数字 int num[NUM]; int lottery[MAXN]; void combine(int n, int m); 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); system("pause"); return 0; } 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]); } getchar(); printf("\n"); } } }
实现结果:
三、总结与提升
回溯法的3个要素:解空间、约束条件、状态树。