算法第五章作业
2019-12-15 13:27 绮罗生 阅读(122) 评论(0) 收藏 举报1.什么是回溯法?
回溯法,顾名思义就是回到曾经的结点的一种算法。在我的理解当中,回溯法就是我们在列出一系列解时,需要有抉择,假设我现在有两条路可以选择,我选择了第一条后发现这条路并不一定比第二条好,所以用回溯法返回到上一次选的的路径,然后再继续进行下去。
回溯法如果要遍历一遍的话效率会很低,所以为了提高效率我们要适当地使用“剪枝”地方法使得它能够在面对某些情况时少走一些“冤枉路”,剪枝又分为宽松型和严格型,都能提高回溯法的效率,只不过严格回溯效率会更高。在解决某一个问题时如果可以使用回溯法,也可以使用动态规划,具体问题具体分析,看使用哪一种方法效率更高。
2.请说明“子集和”问题的解空间结构和约束函数。
解空间结构:
正整数集合S={x1,x2,…,xn}对应的的一个子集S1,S1中的元素之和为c。
约束函数:
其约束函数为 if (sum + a[t] <= c)/ else ,如果加上当前结点的值小于问题所要求的子集和目标值,则向右子树深度优先搜索,否则向左子树深搜。
代码实现:
1 #include<iostream> 2 using namespace std; 3 4 #define N 10000 5 6 int n, c, rest = 0; 7 8 int a[N]; 9 int x[N]; 10 int sum = 0; 11 12 int backtrack(int t) 13 { 14 if (sum == c) return t; 15 //若当前结点的累计值为c,说明当前结点的路径就是相应子集,返回当前结点深度 16 17 if(t > n) return 0; 18 //sum!=c && 到达叶子结点,说明该叶子的路径不是我们要找的子集 ,故返回0 19 20 rest -= a[t];//rest=a[t+1:n] 21 if(sum + a[t] <= c) //1号分支 22 { 23 x[t] = 1; 24 sum += a[t]; 25 int level = backtrack(t + 1); 26 if (level > 0) return level; 27 sum -= a[t]; 28 } 29 30 if( sum + rest >= c ) //0号分支 31 { 32 x[t]=0; 33 int level = backtrack(t + 1); 34 if (level > 0) return level; 35 //level只有两种情况:0、非0 36 //0表示该分支的所有遍历都找不到相应的子集 37 //非0表示在该分支找到子集了,故往上层函数返回level值,以让上层函数继续往上层返回,达到马上结束递归的作用。 38 } 39 rest += a[t]; 40 41 return 0; 42 } 43 44 int main() 45 { 46 cin >>n >> c; 47 48 for (int i = 1; i <= n; i++) 49 { 50 cin >> a[i]; 51 rest += a[i]; 52 } 53 for (int i = 0; i <= n; i++) 54 x[i] = 0; 55 sum = 0; 56 int level = backtrack(1); 57 if(level > 0) //若level非0,说明找到了相应子集,该子集的路径深度为level 58 { 59 for(int i = 1; i < level; i++) 60 if (x[i]) cout << a[i] << " "; 61 cout << endl; 62 } 63 else cout << "No Solution!"; 64 return 0; 65 }
3.请说明在本章学习过程中遇到的问题及结对编程的情况。
在理解回溯法的时候觉得很简单,但自己亲手实践发现还是有困难。尤其是自己实现“剪枝”算法的时候觉得并没有想象中那么容易。
结对编程和伟严卓蓉一起,还是感觉从她们身上学到了很多。
浙公网安备 33010602011771号