回溯法算法步骤&n皇后问题的详细程序(C++)

/*

回溯法有“通用解题法”之称,可以系统的搜索问题的所有解,既有系统性也有跳跃性。

它在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树。算法搜索至洁空间树

的任一结点时,先判断该结点是否包括该问题的解,如果肯定不包含,则跳过对以该结点为

根的子树的搜索,逐层向其祖先结点回溯;否则进入该子树,继续按深度优先策略搜索。

  回溯法解题的三个步骤:

  (1)针对所给问题,定义问题的解空间;

  (2)确定易于搜索的解空间结构;

  (3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

 递归法实现回溯:

其中t表示递归深度,n用来控制递归深度。当t>n时,算法以搜索至叶结点。此时,由output(x)记录或输出

得到的可行解x。for循环中的f(n,t)和g(n,t)分别表示在当前扩展结点处未搜索过的子树的起始编号和终止编号。

h(i)表示在当前扩展结点处x[t]的第i个可选值。constraint(t)和bound(t)是当前扩展结点处的约束函数和

限界函数。

调用一次backtrack(1)即可完成整个回溯搜索过程。

  void backtrack(int t)

  {

if(t>n)

output(x);

else

{

for(i=f(n,t); i<=g(n,t); i++)

{

x[t]=h(i);

if(constraint(t)&&bound(t))

backtrack(t+1);

}

}

  }

  采用树的非递归深度优先遍历算法,可将回溯法表示为一个非递归迭代过程

 void iterativeBack()

 {

 int t=1;

 while (t>0)

 {

 if(f(n,t)<g(n,t))

 for(i=f(n,t); i<=g(n,t); i++)

 {

 x[t]=h(i);

 if(constraint(t)&&bound(t))

 {

 if (solution(t))

 output(x);

 else t++;

 }

else t–;

 }

 }

  }

  在回溯法的搜索过程中动态产生问题的解空间,在任何时刻,算法只保存从根结点到当前扩展结点

的路径。如果解空间树中从根结点到叶结点的最长路径长度为h(n),则回溯法所需的计算空间为O(h(n)).

而显示地存储整个解空间则需要O(2^h(n))或O(h(n)!)内存空间

————————————————————————————

当所给的问题是从n个元素的集合S中找出S满足某种性质的子集时,相应的解空间树为自己树。O(2^n)

如0-1背包问题,装载问题,符号三角形问题,最大团问题,图的m着色问题,n皇后问题

当所给问题是确定n个元素满足某种性质的排列是,相应的解空间树称为排列树。O(n!)

如批处理作业调度,旅行售货员问题,圆排列问题,电路板排列问题

用回溯法搜索子集树的一般算法可描述为:

  void backtrack(int t)

  {

 if(t>n)

 output(x);

 else

 {

 for (i=0; i<=1; i++)

 {

 x[t]=i;

 if(constraint(t)&&bound(t))

 backtrack(t+1);

 }

 }

  }

  用回溯法搜索排列树的一般算法可描述为:

  void backtrack(int t)

  {

 if(t>n)

output(x);

 else

 {

 for (i=t;i<=n; i++)

 {

 swap(x[t],x[i]);

 if(constraint(t)&&bound(t))

 backtrack(t+1);

 swap(x[t],x[i]);

 }

 }

  }

*/

 

#include <iostream>

#include <cmath>

using namespace std;

class NQueen

{

private:

int numOfQueen;
//the number of queens

int numOfanswer;
//the number of answers

int *queen;

public:

NQueen();

NQueen(int m);

~NQueen();

bool place(int k);

void backtrack(int t);

void showQueen();

};

NQueen::NQueen()

{

numOfQueen = 0;

numOfanswer = 0;

queen = new int [1];

}

NQueen::NQueen(int m)

{

numOfQueen = m;

numOfanswer = 0;

queen = new int [m+1];

for(int i=0;i<=m;i++)

{

queen[i]=0;

}

}

NQueen::~NQueen()

{

delete []queen;

cout<<“queens are deleted!”<<endl;

}

void NQueen::showQueen()

{

for(int i=1;i<=numOfQueen;i++)

cout<<queen[i]<<”  “;

cout<<endl;

}

bool NQueen::place(int k)
//the constraint function

{

for (int j=1; j<k; j++)

if((fabs(k-j)==fabs(queen[j]-queen[k]))||(queen[j]==queen[k]))

return false;

return true;

}

void NQueen::backtrack(int t)

{

int i=0;

if(t>numOfQueen)

{

numOfanswer++;

showQueen();

}

else

{

for(i=1; i<=numOfQueen; i++)

{

queen[t]=i;

if(place(t))

backtrack(t+1);

}

}

}

int main()

{

int m1=4,m2=8;

NQueen Q1(m1);

cout<<“the number of queens are :”<<m1<<endl;

Q1.backtrack(1);

NQueen *Q2 = new NQueen(m2);

cout<<“the number of queens are :”<<m2<<endl;

Q2->backtrack(1);

return 0;

}

    原文作者:回溯法
    原文地址: https://blog.csdn.net/zhangchao3322218/article/details/8091047
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞