先贴代码,分递归回溯法和非递归回溯法
递归回溯法,代码如下:
//test.cpp : Defines the entry point for the console application.//#include"stdafx.h"#include#include
using namespacestd;int a[9] = {0};int n = 8;int count = 0;bool check(int arr[], intn)
{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(inta[])
{
printf("第%d种情况:", count);for (int i = 1; i <= n; ++i)
printf("%d",a[i]);
printf("\n");
count++;
}void searchQueens8(intr)
{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;inttop;voidprintQueenStack()
{
printf("No.%d:", sum);for (int i = 1; i <= N; ++i)
printf("%d", cszStack[i]);
printf("\n");
sum++;
}//k表示第k行
bool judge(intk)
{if (k == 1)return true;inti;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;
}voidputQueen()
{
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--;
}
}
}voidinitStack()
{for (int i = 0; i <= N; ++i )
cszStack[i]= 0;
sum= 0;
top= 0;
}voidsearchQueueStack()
{
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;} // 回溯
}
}