回溯算法总结

 一、   回溯算法是一种组织搜索的一般技术,有“通用的解题法”之称,它可以系统地搜索一个问题的所有解或任意解。

    1、应用回溯算法时,需要明确定义问题的解空间,问题的解空间应至少包含问题的一个最优解。

   /2、定义了问题的解空间后,还应将解空间很好的组织起来,使得回溯法能方便的搜索解空间,通常组织成数或图的形式。

   /3、从树根到叶子节点的任一路径表示解空间的一个元素。

二、回溯算法的基本思想:

    在确定了解空间的基本结构后,回溯从开始结点出发,以深度优先的方式搜索整个解空间。这个开始结点成为一个活结点,同时成为当前的扩展结点。通过当前的扩展节点,搜索向深度方向进入一个新的结点。这个新的节点成为一个新的活结点,并成为当前的扩展结点。若在当前扩展结点处不能再向深度方向移动,则当前扩展结点成为一个死结点。此时回溯到最近的一个活节点处,并使当前的的活节点成为扩展结点。回溯算法以这样的方法递归搜索整个空间树,直至满足终止条件。

三、算法基本结构与相关问题:

1、递归回溯:

void Backtrack(int t)
{
 if (t > n)
 {
  output(x);
 }
 else
 {
  for (int i = f(n,t); i < g(n,t); ++i)
  {
   x[t] = h(i);
   if (Constraint(t)&&Bound(t))
    Backtrack(t+1);
  }
 }

}

 2、迭代回溯

如果采用树的非递归深度优先搜索遍历算法;也可以将回溯法表示为一个非递归的迭代过程。如下:

void iterativeBacktrack(void)

{

     int t = 1;

    while(t  > 0)

    {

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

       {

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

               {

                     x[t] =h(i);

                     if (Constraint(t)&&Bound(t))

                    { 

                           if (Solution(x)) output(x);

                           else ++t;

                      }// end if

                      else   –t;

        }// end for

    }// end while

}// end function iterativeBacktrack

1、0-1揹包问题。

2、旅行商问题。

子集数与排列数

3、装载问题。

4、图的m着色问题。

5、n皇后问题。

6、流水作业调度问题。

7、子集和问题。

四、题目:

问题:给出一组候选数字(C)和目标数字(T),找出C中所有的组合,使组合中数字的和为T。C中每个数字在每个组合中只能使用一次。

样例

给出一个例子,候选数字集合为[10,1,6,7,2,1,5] 和目标数字 8  ,

解集为:[[1,7],[1,2,5],[2,6],[1,1,6]]

代码:

class Solution {  
public:  
    /** 
     * @param num: Given the candidate numbers 
     * @param target: Given the target number 
     * @return: All the combinations that sum to target 
     */  
    vector<vector<int> > combinationSum2(vector<int> &num, int target) {  
        // write your code here  
        set<vector<int> > r;  
        vector<int> cur;  
        sort(num.begin(),num.end());  
        combination(cur,num,0,0,target,r);  
        vector<vector<int> > ret;  
        copy(r.begin(),r.end(),back_inserter(ret));  
        return ret;  
    }  
    void combination(vector<int> cur,vector<int> &num,int index,int curSum,int target,set<vector<int> >&ret)  
    {  
        if(curSum>target)  
            return;  
        if(curSum==target)  
        {  
            ret.insert(cur);  
            return;  
        }  
        if(index==num.size())  
            return;  
        combination(cur,num,index+1,curSum,target,ret);  
        cur.push_back(num[index]);  
        combination(cur,num,index+1,curSum+num[index],target,ret);  
    }  
};  

点赞