回溯算法实际上是一个类似枚举的搜索尝试过程,主要是在搜索尝试中寻找问题的解,当发现已不满足求解条件时,就回溯返回,尝试别的路径。
回溯法是一种选优搜索法,按选优条件向前搜索,以达到目的。但是当探索到某一步时,发现原先选择并不优或者达不到目标,就退一步重新选择,而满足回溯条件的某个状态的点称为“回溯点”
许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。
基本思想:
在包含问题的所有解的空间树中,按照深度优先搜索的策略,从根节点出发深度搜索解空间树。当探索到某一节点时,要先判断
该节点不包含问题的解,则逐层向其祖先节点回溯,其实回溯法就是对隐式图的深度优先搜索算法。
若用回溯法求问题的所有解时,要回溯到跟,且根节点的所有可行的子树都要已被搜索遍才结束。
而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。
二.回溯法典型:
1.八皇后问题
问题;八皇后问题是一个以国际象棋为背景的问题,如何能够在8*8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行,总行或斜线上。
转化规则:
1 #include <iostream> 2 #include <algorithm> 3 #include <iterator> 4 #include <vector> 5 6 using namespace std; 7 8 //位置冲突算法 9 bool isMeet(int a[], int n)//a[]位置数组,n皇后个数 10 { 11 for (int i = 2; i <= n; ++i)//i:位置 12 for (int j = 1; j < i; ++j)//j:位置 13 if ((a[i] == a[j]) || (abs(a[i] - a[j]) == i - j))//1:在一行;2:在对角线上 14 return false; //冲突 15 return true;//不冲突 16 } 17 //八皇后:枚举算法 18 19 //主函数 20 int main() 21 { 22 int a[9] = { 0 }; //用于记录皇后位置:(第0行0列我们不用)。如:a[3] = 4;表示第3列第4行位置有皇后 23 int count = 0; //用于计数 24 25 for (a[1] = 1; a[1] <= 8; ++a[1]) 26 for (a[2] = 1; a[2] <= 8; ++a[2]) 27 for (a[3] = 1; a[3] <= 8; ++a[3]) 28 for (a[4] = 1; a[4] <= 8; ++a[4]) 29 for (a[5] = 1; a[5] <= 8; ++a[5]) 30 for (a[6] = 1; a[6] <= 8; ++a[6]) 31 for (a[7] = 1; a[7] <= 8; ++a[7]) 32 for (a[8] = 1; a[8] <= 8; ++a[8]) 33 { 34 if (!isMeet(a, 8))//如果冲突,则继续枚举 35 continue; 36 else 37 ++count; 38 } 39 cout << count << endl; 40 system("pause"); 41 return 0; 42 }