回溯法 是 一种 在 穷举 中,裁剪 不满足 条件 的 分支,已达到 提高 效率的 方法。其基本原型 是 树的 先序遍历,从 树根 到 树叶的路径 是 问题的 一个 解。
回溯法的基本框架 = 确定 解空间 + 深度优先遍历 + 裁剪函数 + 确定结果函数
其中 解空间,分为 子集树 和 排序树。
递归算法通用 模板如下:
回溯法对解空间作深度优先搜索,因此,在一般情况下用递归方法实现回溯法。
// 针对N叉树的递归回溯方法
void backtrack (int t)
{
if (t > n) {
// 到达叶子结点,将结果输出
output (x);
}
else {
// 遍历结点t的所有子结点
for (int i = f(n,t); i <= g(n,t); i ++ ) {
x[t] = h[i];
// 如果不满足剪枝条件,则继续遍历
if (constraint (t) && bound (t))
backtrack (t + 1);
}
}
}
下面的 三个例子 都是 根据 这个 模板 来 写的。// Backtrack.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <cstring>
#define SET_MAX_SIZE 1000
static bool set[SET_MAX_SIZE];
//获得幂集
//times 表示 当前递归层的层数,从0 层开始
//n 表示 集合的数量
void getPowset(int times,int n){
if (times >= n)
{
for (int i = 0; i < n; i++)
{
if (set[i] == true)
{
printf("%d\t",i+1);
}
}
printf("\n");
}
else
{
for (int i = 0; i < 2; i++)
{
set[times] = i;getPowset(times+1,n);
}
}
}
//打印string的所有子串
//times表示当前 递归层数
void getAllSubChar(int times,char * string){
int len = strlen(string);
if (times >= len)
{
for (int i = 0; i < len; i++)
{
if (set[i] == true)
{
printf("%c\t",string[i]);
}
}
printf("\n");
}
else{
for (int i = 0; i < 2; i++)
{
set[times] = i;getAllSubChar(times+1,string);
}
}
}
//打印集合中所有等于 N 的组合.
void getAllEqual(int times,int arrayLen,int * array,int equal){
int len = arrayLen;
if (times >= len)
{
int sum = 0;
for (int i = 0; i < len; i++)
{
if (set[i] == true)
{
sum += array[i];
}
}
if (sum == equal)
{
for (int i = 0; i < len; i++)
{
if (set[i] == true)
{
printf("%d\t",array[i]);
}
}
printf("\n");
}
}
else
{
for (int i = 0; i < 2; i++)
{
set[times] = i;
int sum = 0;
//裁剪..剪掉 不符合的条件.
for (int i = 0; i <= times; i++)
{
if (set[i]== true)
{
sum += array[i];
}
}
if (sum <= equal)
{
getAllEqual(times+1,arrayLen,array,equal);
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
printf("1~ N 的幂集,请输入N值:");
int n;
scanf("%d",&n);
printf("1~%d的幂集为:\n",n);
getPowset(0,n);
char string[SET_MAX_SIZE];
printf("请输入字符串的:");
scanf("%s",string);
printf("%s的所有子字符串如下:\n",string);
getAllSubChar(0,string);
printf("查找集合(3,2,5,6,7,8,10,20,4,15)中 等于 10的 组合\n");
int array[] = {3,2,5,6,7,8,10,20,4,15};
getAllEqual(0,sizeof(array)/sizeof(int),array,10);
return 0;
}