回溯算法通常用递归来实现,通常有下面两种算法框架(阅读回溯算法实现代码可以依照下面的框架来理解):
算法框架一:
procedure Try(k:integer);
begin
for i:=1 to 算符种类 Do
if 满足条件 then
begin
保存结果
if 到目的地 then 输出解
else Try(k+1)
恢复,保存结果之前的状态,回溯一步
end;
end;
算法框架二:
procedure Try(k:integer);
begin
if 到目的地 then 输出解
else:
for i:=1 to 算符种类 Do
if 满足条件 then
begin
保存结果
Try(k+1);
end;
end;第二种算法框架更加简洁,很多人看别人的回溯算法代码实现都纳闷怎么没有发现代码中有回溯的操作,而觉得回溯算法代码有问题,其实这是由于代码是参照第二种框架来写,这种框架没有直接回溯操作。但是实际上本质上和第一种算法框架相同
下面运用第二种算法框架 实现n皇后问题
题目:
在n * n的国际象棋盘上放置n个皇后,使它们彼此互相不攻杀。皇后攻杀条件:处于同一行,或同一列,或同一斜线的皇后彼此攻杀。试给出全部方案
//编程实现n皇后问题 其中n由define规定
#include <stdio.h>
#include <math.h>
#define N 5
int col[N+1];
//输出结果
void Output()
{
for(int i=1;i<=N;i++)
{
printf("(%d,%d)\n",i,col[i]);
}
printf("\n");
}
//求解函数 i之前的解已经确定的基础上 求其它
void Queen(int i,int n)
{
if(i>n) //当满足此条件 说明 到达目的地
Output();
else
{
for(int j=1;j<=n;++j)
{
int k=1;
col[i]=j;
while(k<i)
{
if((col[k]-col[i])*(fabs(col[k]-col[i])-fabs(k-i))!=0)
{ //满足此条件 说明col[k]当前放置的位置没有发生冲突
k++; //保存结果
if(k==i)
Queen(i+1,n);//递归
}
else
{
break;
}
}
}
}
}
int main()
{
printf("the answer is:\n");
for(int i=1;i<=N;i++)
{
col[1]=i; //设置第一行的 列值 为i
Queen(2,N);
}
}
~
~