学习回溯,分支定界和动态编程算法有哪些好的资源?

时间:2012-08-25 10:49:09

标签: algorithm data-structures dynamic-programming backtracking branch-and-bound

CLRS似乎不包括bactracking / branch-and-bound。我在线尝试了几种资源,虽然我得到了这些资源,我无法编写代码,比方说,背包问题。所以,我想要的东西可能会带来问题,并用这3种方法解决它,至少给出了伪代码。 或者你认为有用的任何资源都会有所帮助。

2 个答案:

答案 0 :(得分:3)

在使用回溯,分支/绑定等的算法中,通常存在解空间的概念和搜索空间。该算法的目标是遍历搜索空间以到达解空间中的某个点,并且通常是某个度量被认为是最优的点,或者确定解空间是空的(不访问搜索空间中的每个元素)

第一步是定义一种机制,以高效的格式表达搜索空间中的元素。表示应该允许您表示哪些元素构成解空间,通过用于度量的度量来评估元素质量的方法,确定可以从当前状态到达的相邻元素的方法等等。

通常,这些算法将遍历搜索空间直到找到解决方案,或者如果没有解决方案将退出。遍历通过访问一系列点来进行,通常并行地探索搜索空间。这是分支方面;您正在决定访问搜索空间的某些部分。

在搜索空间的遍历期间,他们可以确定特定路径不值得,因此他们可以决定他们不会探索从路径可到达的搜索空间的部分。这是非常有限的方面。

通常使用部分解决方案来完成空间的遍历。例如,如果您有一个由8位表示的搜索空间,则可以将固定值分配给8位中的两个特定位,然后为剩余的6位表示的空间搜索所需的解。您可能会发现将两位特定分配给固定值会导致无法存在解决方案(或解决方案的质量非常差)。然后,您可以绑定搜索空间,以便算法不会通过为这两个位分配特定的固定值来探索该子空间中的任何其他元素。

对于基于回溯的系统,伪代码是微不足道的。挑战在于寻找有效的表示来代表搜索空间,代表部分解决方案,找出特定解决方案的有效性,提出规则来确定预先采用哪条路径,制定衡量解决方案质量的指标,搞清楚什么时候回溯,或者回溯多远等等......

StateStack.push(StartState)
loop{
  curState = StateStack.top
  nextState = calculateNextState(curState)
  StateStack.push(nextState)
  if(reachedFinalGoal(nextState)){
     break;
  }
  if(needToBackTrack(StateStack)){
     curState = nextState
     stateToBackTrackTo = calculateStateToBackTrackTo(stateStack)
     while(curState != stateToBackTrackTo){
       stateToGoBackTo = stateStack.pop
       curState = RollBackToState(stateToGoBackTo)
  }
}

答案 1 :(得分:0)

这些是搜索技术,而不是算法。首先,您应该清楚地了解搜索空间是什么。例如。在背包问题的情况下,该问题包括可用对象的所有可能子集。有时存在限制哪些解决方案有效以及哪些解决方案无效,例如那些超过背包总体积的对象组无效。您还应该有明确定义的目标(此处所选对象的总价值)。

实际上,维基百科包含Branch and Bound的非常准确的描述。它是相当高级的,但任何更详细的描述都需要对搜索空间的结构进行假设。对于backtracking,甚至有一些伪代码,但同样非常笼统。

另一种(可能更好的)方法是找到这些技术的示例应用并研究它们。在CLRS中至少有几种涉及DP的算法,如果需要,你肯定可以更多地进行谷歌搜索。