分支限界法实现最优装载c++_工橙院科普|常用算法之——回溯法

回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原选择不优或达不到目标,就退一步重新选择,这种走不通就退回再走的技术为回溯法。

在我们求解某些问题时,常常会把答案一一枚举(列举),然後再检查答案的是否正确。但一一枚举会非常耗时,而且常常枚举出来的数量远多于所需要的答案。原因在于在枚举进行到一半的时候,如果该解决问题的路径是错的,还是会不断的继续向下枚举。但其实我们可以在发现这条路径不可能找出答案的时候,就不再往下枚举了,这种思想就是回溯(Backtracking)算法。

回溯法算法基本思想

回溯算法实际上是一个类似枚举的搜索尝试过程,是在搜索尝试过程中寻找问题的解。当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原选择不优或达不到目标,就退一步重新选择,这种走不通就退回再走的技术为回溯法。而满足回溯条件的某个状态的点称为“回溯点”。

1、回溯法的适用:

许多问题,当需要找出它的解集(全部解)或要求回答什么解是满足某些约束条件的最优解时,往往要使用回溯法。

2、有组织的穷举式搜索:

回溯法的基本做法是搜索或者有的组织穷尽搜索。避免搜索所有的可能性。即避免不必要的搜索。这种方法适用于解一些组合数相当大的问题。

3、搜索解空间树:

回溯法在问题的解空间树中,按深度优先策略(DFS),从根结点出发搜索解空间树。

算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。

如果肯定不包含(剪枝过程),则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。

为了实现回溯,我们先弄明白以下两个问题:

1)首先应该明确问题的解空间。

2)其次是组织解空间以便它能用以被搜索到。

回溯法解题的一般步骤

  1. 针对所给问题,确定问题的解空间:首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解。
  2. 确定结点的扩展搜索规则
  3. 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

递归回溯

迭代回溯

61bc8f69e67c1042062530d5d845b756.png

回溯法的应用举例:

排列问题:

3b316b54a50b3040ad29de208c20191f.png

举个例子来说:如果对"ABCD"四个字母进行排列,我们知道有24(4!)种答案,如果枚举所有可能的答案,就会产生生AAAA,AAAB,...AADD這種不符合的答案,而且总共会产生64(4^4)种結果,比24大了不少。

程序代码如下:

#include

#include

using namespace std;

string str;

string Ans; //保存答案

bool choosed[100] = {0}; // choosed[i]==1表示编号i已經出現過

void backtracking(const int &N);

int main()

{

str = "ABCD";

backtracking(4);

}

void backtracking(const int &N) // N表示有N个字母

{

if (Ans.size() == N) { // 终止条件检查

cout << Ans << endl;

return;

}

for (int i = 0; i < N; ++i) {

if (choosed[i] == 0){ // 如果這个编号还没出现过 Ans.push_back(str[i]); // 将它放入Ans

choosed[i] = 1; // 並且让choosed[i]变成1,避免之后选到

backtracking(N);

Ans.pop_back();

choosed[i] = 0;

}

}

}


可以发现回溯算法在每次遍历前都会先检查答案的可行性,必须确认“到目前为止都是正确的”才会继续向下,因此就能避免产生错误的答案,所以上面的例子就少了40个错误的答案。

许多复杂的,规模较大的问题都可用回溯法,回溯法有“通用解题方法”的美称。

应用回溯法解决的一些经典问题:

1)装载问题

2)批处理作业调度

3)符号三角形问题

4)n后问题

5)0-1背包问题

6)最大团问题

7)图的m着色问题

8)旅行售货员问题

9)圆排列问题

10)电路板排列问题

11)连续邮资问题

b658af21bbcbeb3a3a3add3a84635dc9.png

添加微信,获得更多资讯~长按扫码可添加

0d0f5edffb1f77c793334de93f59c4e2.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值