先贴代码,分递归回溯法和非递归回溯法
递归回溯法,代码如下:
// test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <stdio.h> using namespace std; int a[9] = {0}; int n = 8; int count = 0; bool check(int arr[], int n) { for (int i = 2; i <= n; ++i) for(int j = 1; j <= i-1; ++j) if (arr[i] == arr[j] || (abs(arr[i]-arr[j]) == abs(i-j))) return false; return true; } void printQueens(int a[]) { printf("第%d种情况:", count); for (int i = 1; i <= n; ++i) printf("%d",a[i]); printf(" "); count++; } void searchQueens8(int r) { if (r > n) printQueens(a); for (int i = 1; i <= n; ++i) { a[r] = i; if (check(a, r)) { searchQueens8(r+1); } } } int _tmain(int argc, _TCHAR* argv[]) { searchQueens8(1); return 0; }
非递归回溯法,代码如下:
#pragma once #include "stdafx.h" const int N = 8; int cszStack[9]; int sum = 0; int top; void printQueenStack() { printf("No.%d:", sum); for (int i = 1; i <= N; ++i) printf("%d", cszStack[i]); printf(" "); sum++; } // k表示第k行 bool judge(int k) { if (k == 1) return true; int i; for (i = 1; i < k; ++i) { if (cszStack[i] == cszStack[k]) return false; if (abs(k-i) == abs(cszStack[k] - cszStack[i])) return false; } return true; } void putQueen() { top = 1; while(top > 0) { cszStack[top]++; // 摆放一个皇后 // 如果第top行的皇后没有摆放出第8列,那就一直找到它在top行的合法位置 while((cszStack[top] <= N) && (!judge(top))) cszStack[top]++; if (cszStack[top] <= N) { if (top == N) { printQueenStack(); // 输出结果 } else { top++; cszStack[top] = 0; } } else { // 在第top行8列全部不能放置皇后,说明前面几行的摆放不合理,所以要退回上一行 top--; } } } void initStack() { for (int i = 0; i <= N; ++i ) cszStack[i] = 0; sum = 0; top = 0; } void searchQueueStack() { initStack(); putQueen(); } int _tmain(int argc, _TCHAR* argv[]) { //SearchQueens8(1); searchQueueStack(); return 0; }
指导思想:
走不通,就掉头;
检查合格才继续往下走;遇到不合格就是掉头;
能进则进,不能进则换,不能换则退;
解空间:一颗树空间
扩展规则:深度优先策略
设计过程:(1)确定问题的解空间;(2)确定结点的扩展规则;(3)搜索解空间
退回到上一状态的过程叫做回溯,枚举下一个状态的过程叫做递归;
回溯就像人走迷宫,先选择一个前进方向尝试,一步步试探,在遇到死胡同不能再往前的时候就会退到上一个分支点,另选一个方向尝试,而在前进和回撤的路上都设置一些标记,以便能够正确返回,直到达到目标或者所有的可行方案都已经尝试完为止。
回溯法应用——算法说明
(1) 八皇后问题中的核心代码
遍历过程函数;check函数;
(2) 解决此类问题的核心内容
解空间树的搜索算法;估值/判断函数:判断哪些状态适合继续扩展,或者为答案状态;
递归算法框架:
int a[n];
Queens(int k)
{
if (k > n)
// 即表示最后一个皇后摆放完毕,输出结果;
else
//枚举k个皇后所有可能路径
for (int i = 下界;I <= 上界; i++)
{// 依次从列顶端开始搜索,一直到列底端,直到找到合适的位置,如果未找到,自动返回上层递归
a[k] = i;
if (check(a,k))
// 递归摆放下一个皇后Queens(k+1);
}
}
非递归算法框架:
int a[n],i;
初始化数据a[];
i = 1;
while (i > 0(有路可走)) and (未达到目标)// 还未回溯到头
{
if (i == n)
搜索到一个解,输出;// 搜索到叶结点
else
{
a[i]第一个可能的值
while(a[i]不满足约束条件且在搜索空间内)
a[i]下一个可能的值;
if(a[i]在搜索空间内)
{ 标识暂用的资源;i=i+1;} // 扩展下一个结点
else
{清理所占的状态空间;i=i-1;} // 回溯
}
}
参考链接:https://wenku.baidu.com/view/d1e9d6fe02020740bf1e9bce.html?from=search