一、 你对回溯算法的理解
l 在我的观念里,回溯法就是“暴力穷举”+“答案遍历”
l 用书上的话来说就是:回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标,当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择。实际上就是穷举法的改进。回溯法可以避免搜索所有可能的解,可用于求解大规模问题。
l 另外一个需要注意的点就是:为了提高回溯法的效率,我们通常会用剪枝函数和限界函数来避免回溯法进入到一些冗余的枝丫,从而降低算法的时间复杂度。
二、 请说明“子集和”问题的解空间结构和约束函数
l 解空间结构:
正整数集合S={x1,x2,…,xn}对应的的一个子集S1,S1中的元素之和为c。
l 约束函数:
if (sum + a[t] <= c)
如果sum加上a [t] 后小于等于目标值c 那么可取,如果大于c的话 则舍去这个结点a[t]
算法实现:
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int n,c,flag1=0;
int a[10005],flag[10005];
int sum=0,summ=0;
void dfs(int num){
if(flag1){
return;
}
if(sum==c){
for(int i=1;i<num;i++){
if(flag[i]){
cout<<a[i]<<" ";
}
}
flag1=1;
return;
}else if(sum>c){
return;
}else{
if(num<=n){
sum+=a[num];
flag[num]=1;
dfs(num+1);
sum-=a[num];
flag[num]=0;
dfs(num+1);
}
}
return;
}
int main(){
cin>>n>>c;
for(int i=1;i<=n;i++){
cin>>a[i];
summ+=a[i];
}
if(summ<c){
cout<<"No Solution!\n";
}else{
dfs(1);
if(!flag1){
cout<<"No Solution!\n";
}
}
return 0;
}
三、 请说明在本章学习过程中遇到的问题及结对编程的情况
本章最大的问题就是backtrack函数的写法,以及约束函数的思想。
需要对题目的思路清晰,以及想清楚回溯前要进行什么操作,然后在回溯backtrack之后进行与之对应的相反的操作。
关于结对编程,一个学期下来,向明杰学习到了很多,无论是编程经验,还是算法思想,他都教了我很多东西,我十分感谢郑老师开设的这个环节,让我这个小菜鸡能够向厉害的人学习~感谢!