算法第五章作业

回溯法的理解

基本思想:

构建问题的解空间树,在其解空间树中,从根节点出发,进行深度优先搜索。在搜索过程中,对解空间

树的每个结点进行判断,判断该结点是否包含问题的解,若肯定不包含,则跳过对以该结点为根的子树的

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

步骤:

1、针对所给问题,定义其解空间

2、确定易于搜索的解空间结构

3、深度优先搜索其解空间,并在搜索过程中用剪枝函数避免无效搜索

剪枝:

回溯法搜索空间树时,常用限界函数和约束函数避免无效搜索,其中约束函数将不满足约束的子树剪去,

限界函数将得不到最优解的子树。一般可以利用这两种剪枝方式提升算法的效率,避免大量的不必要搜索。

 

例题讲解

 

 

题意概述:一道很明了的回溯法的题目,直接思考解空间,约束函数及写法即可。

 

解空间:  子集和问题的解空间为子集树结构。其中子集树的每一层表示是否选择该数值。

 

约束函数:

      当递归的层数大于等于n时,表示当前层次已经大于元素的个数,接下来的为无用搜索,直接剪去该

      结点的搜索即可当搜索到当前结点后所得的值大于题目中的c,则表示接下来的搜索不可能找到等于c的

      答案,直接剪去以该节为根的子树的搜索即可。

 

AC代码:

 1 #include<iostream>
 2 using namespace std;
 3 int sum,c,n;
 4 bool flag=0;
 5 int a[10005],vis[10005];
 6 void backtrack(int m){
 7     if(flag) return;
 8     if(sum==c){
 9         flag=1;
10         for(int i=0;i<m;i++){
11             if(vis[i]) cout<<a[i]<<" ";
12         }
13         cout<<'\n';
14         return;
15     }
16     if(sum>c||m==n) return;
17     if(sum+a[m]<=c){
18         sum+=a[m];
19         vis[m]=1;
20         backtrack(m+1);
21         vis[m]=0;
22         sum-=a[m];
23     }
24     backtrack(m+1);
25 }
26 int main(){
27     cin>>n>>c;
28     int tot=0;
29     for(int i=0;i<n;i++){
30         cin>>a[i];
31         tot+=a[i];
32     }
33     if(tot<c){
34         cout<<"No Solution!"<<'\n';
35         return 0;
36     }
37     backtrack(0);
38     if(!flag) cout<<"No Solution!"<<'\n';    
39     return 0;
40 }
View Code

 

 

 

心得体会及结对编程情况:

    这次回溯法的学习应该是这学期里最难的了,每个问题都要仔细思考解空间和约束函数,但是熟悉解法和掌握技巧之后感觉也还行。

           结对编程中互相学习互相交流,促进了自己的学习效率,使自己更加进步。

posted on 2019-12-16 13:50  maskkkk  阅读(137)  评论(0编辑  收藏  举报

导航