一、对回溯算法的理解
回溯算法首先需要构建解空间,然后对解空间进行遍历。为了降低时间复杂度,需要建立限界函数或约束函数,避免去遍历明显不可能的分支。
二、“子集和”问题的解空间结构和约束函数
“子集和”问题可以描述为一棵完全二叉树,每一层的左子树表示对选择当前元素,右子树表示不选择当前元素。
对于约束函数的构建:用rest表示尚未选择的元素的总和,sum表示已选择元素的总和,a[t]表示当前正在元素,result表示需要匹配的目标值。if(sum+a[t]<=result),选择当前元素,sum +=a[t],进入左子树;if(sum+a[t]>=result),,不选择当前元素,进入右子树。
#includeusing namespace std;int n;int *a;int *p;int sum=0,rest=0,flag=0;int result;void Backtrack(int t){ if(sum==result) { flag=1; return ; } if(t>n) return ; rest -=a[t]; if(sum+a[t]<=result){ p[t]=1; sum=sum+a[t]; Backtrack(t+1); if(flag) return; sum -=a[t]; } if(sum+rest>=result){ p[t]=0; Backtrack(t+1); if(flag) return; } rest +=a[t]; }int main(){ cin>>n>>result; a=new int[n+1]; p=new int[n+1]; for(int i=1;i<=n;i++){ cin>>a[i]; rest +=a[i]; p[i]=0; } Backtrack(1); if(!flag) cout<<"No Solution!"; else for(int i=1;i<=n;i++) if(p[i]) cout< <<" "; return 0;}
三、在本章学习过程中遇到的问题及结对编程的情况
回溯法的思想理解起来不难,但是用回溯法解题需要比较高的技巧,限界函数和约束函数的选择是个很大的问题。结对编程时曾和队友对函数的构建出现了较大的分歧,最后还是和平解决了。