回溯法 子集树和排序树

当所给问题是从n个元素的集合S中找出满足某种性质的子集时,解空间为 子集树。例如: 0-1背包问题 
 
当所给问题是从n个元素的集合S中找出满足某种性质的排列时,解空间为 排列树。例如: 旅行售货员问题
 
 
回溯法搜索子集树算法描述为:
 
void backtrack(int  t)
 
{
     if(t>n)   
        output(x);
     else
        for(int i=0; i<=1; i++) //注意,这里的0,1 是X[i]的取值范围,t表示层数
      {  
             x[t] = i; 
             if(constraint(t) && bound(t))     
                  backtrack(t+1);
       }  
}
     回溯法搜索排列树的描述为:
 
     void backtrack(int  t)
 
    {
       if(t>n)  
 
           output(x);
       else      
 
          for(int i=t; i<=n; i++) //这里的n表示层数,不要和子集树搞混了
          {
            swap(x[t], x[i]);
            if(constraint(t) && bound(t))      backtrack(t+1);
            swap(x[t], x[i]);       
 
         }     
 
   }
 
 
具体实例:
 
 
 
#include
#include
#define N 3
int x[N+1];
void Backtrace(int t)
{
    if(t>N)
    {
        for(int i=1;i<=N;i++)
        {
            printf("%d ",x[i]);
        }
        printf("\n");
    }
    else
    {
        for(int i=0;i<=1;i++)
        {
            x[t]=i;
            Backtrace(t+1);
        }
    }
}
int main()
{
    memset(x,0,(N+1)*sizeof(int));
    Backtrace(1);
}
--------------------------------------------------------------------------------------------------
 
 
#include
#include
#define N 3
int x[N+1]={0,1,2,3};
void swap(int &a,int &b)
{
    int temp=a;
    a=b;
    b=temp;
}
void Backtrace(int t)
{
    if(t>N)
    {
        for(int i=1;i<=N;i++)
        {
            printf("%d ",x[i]);
        }
        printf("\n");
    }
    else
    {
        for(int i=t;i<=N;i++)
        {
            swap(x[t],x[i]);
            Backtrace(t+1);
            swap(x[t],x[i]);
        }
    }
}
int main()
{
    Backtrace(1);
}
 
子集树实例:
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <iostream>
 4 #include <vector>
 5 #include <queue>
 6 #include <stack>
 7 using namespace std;
 8 
 9 void printVector(vector<int> array );
10 
11 void dfs(vector<int>& array, int dep)
12 {
13     int size =  array.size();
14     if(dep == size)
15     {
16         printVector(array);
17         return;
18     }
19     //dfs to the next level
20     for(int i = 0; i < 2; i++)
21     {
22         array[dep] = i;
23         dfs(array, dep+1);
24     }
25 
26 }
27 
28 
29 void printVector(vector<int> array )
30 {
31     for(int i = 0; i <array.size(); i++)
32         cout << array[i]<< "\t" ;
33     cout << endl;
34 }
35 
36 int main()
37 {
38     vector<int> b ;
39     b.resize(5, 0);
40     dfs(b, 0);
41 
42     return 0;
43 }

打印结果:

0 0 0 0 0
0 0 0 0 1
0 0 0 1 0
0 0 0 1 1
0 0 1 0 0
0 0 1 0 1
0 0 1 1 0
0 0 1 1 1
0 1 0 0 0
0 1 0 0 1
0 1 0 1 0
0 1 0 1 1
0 1 1 0 0
0 1 1 0 1
0 1 1 1 0
0 1 1 1 1
1 0 0 0 0
1 0 0 0 1
1 0 0 1 0
1 0 0 1 1
1 0 1 0 0
1 0 1 0 1
1 0 1 1 0
1 0 1 1 1
1 1 0 0 0
1 1 0 0 1
1 1 0 1 0
1 1 0 1 1
1 1 1 0 0
1 1 1 0 1
1 1 1 1 0
1 1 1 1 1

 
 排序树实例:
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <iostream>
 4 #include <vector>
 5 #include <queue>
 6 #include <stack>
 7 using namespace std;
 8 
 9 void printVector(vector<int> array );
10 
11 int dfs(vector<int>& array, int t)
12 {
13     size_t size =  array.size();
14     if(t == size)
15         printVector(array);
16 
17     //dfs to the next level
18     for(int i = t; i < size; i++)
19     {
20         int j = i;
21         string s;
22         while(j --)
23             s += "\t" ;
24        //cout <<s << "================   start   ==================================;; i =" <<i << endl;
25        swap(array[t],array[i]);
26        //cout <<s << "begin to swap " << array[i]<< " and " << array[t] <<endl; ;
27        //cout <<s << "call dfs -- lvevel " << t+1 <<endl;
28        dfs(array, t+1);
29        //cout <<s << "return dfs -- lvevel " << t+1 <<endl;
30        //cout <<s << "end  to swap" << array[i]<< " and " << array[t] <<endl; ;
31        swap(array[i],array[t]); 
32        //cout <<s << "================= end     ==================================;; i =" <<i << endl;
33     }   
34 
35 }
36 
37 
38 void printVector(vector<int> array )
39 {
40     for(int i = 0; i <array.size(); i++)
41         cout << array[i]<< "\t" ;
42     cout << endl;
43 }
44 
45 int main()
46 {
47     vector<int> b ;
48 #if 1
49     b.push_back(5);
50     b.push_back(6);
51     b.push_back(7);
52     b.push_back(8);
53 #else
54     b.push_back(4);
55     b.push_back(3);
56     b.push_back(2);
57     b.push_back(1);
58     b.push_back(0);
59 #endif
60 
61     sort(b.begin(), b.end());
62     dfs(b, 0);
63 
64     return 0;
65 }

打印结果

5 6 7 8
5 6 8 7
5 7 6 8
5 7 8 6
5 8 7 6
5 8 6 7
6 5 7 8
6 5 8 7
6 7 5 8
6 7 8 5
6 8 7 5
6 8 5 7
7 6 5 8
7 6 8 5
7 5 6 8
7 5 8 6
7 8 5 6
7 8 6 5
8 6 7 5
8 6 5 7
8 7 6 5
8 7 5 6
8 5 7 6
8 5 6 7

 从结果看,回溯法排序树并不满足 permutation_sequence 的要求。。

递归分析:

转载于:https://www.cnblogs.com/diegodu/p/3805669.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值