第五章作业
你对回溯算法的理解
回溯法,通过深度优先策略,从根结点搜索一个问题的所有解得出答案。回溯法在求问题的解时,要回溯到根,且把所有子树都搜索遍才会结束,当然有些子树不满足条件什么的,就被“剪枝”剪掉了。
请说明“子集和”问题的解空间结构和约束函数
#include<iostream> using namespace std; int flag=0; int m=10000; void backtrack(int a[],int n,int c,int x[],int i,int sum,int left){ if(flag==1) return; if(i==n||left==0){ if(sum==c){ flag=1; for(int j=0;j<n;j++){ if(x[j]==0) continue; else cout<<x[j]<<" "; } } return ; } if(sum+a[i]<=c){ // cout<<"我进去了"<<endl; sum+=a[i]; // cout<<sum<<" sum"<<endl; left=c-sum; // cout<<left<<" left"<<endl; x[i]=a[i]; // cout<<x[i]<<" x[i]"<<endl; backtrack(a,n,c,x,i+1,sum,left); //cout<<"我出去了"<<endl; x[i]=0; // cout<<x[i]<<" x[i]"<<endl; sum-=a[i]; // cout<<sum<<" sum"<<endl; left=c-sum; } if(left>=m){ backtrack(a,n,c,x,i+1,sum,left); // cout<<"我进入else了"<<endl; } } int main(){ int n,c; cin>>n>>c; int a[n]; int sum=0; for(int i=0;i<n;i++){ cin>>a[i]; sum+=a[i]; if(m>a[i]) m=a[i]; } // cout<<"m: "<<m<<endl; // sort(a,a+n); int x[n]; for(int i=0;i<n;i++) x[i]=0; if(sum<c||c<m){ cout<<"No Solution!"; return 0; } else backtrack(a,n,c,x,0,0,c); if(flag==0) cout<<"No Solution!"; return 0; }
解空间其实质就是判断每一个数字是否放入目的数组,与0-1背包问题相似。
约束函数则是:判断当前的left是否比源数组的最小数还小;每一次要加入某一数据时判断是否比目标值大;判断是否已经扫描完源数组。
请说明在本章学习过程中遇到的问题及结对编程的情况
回溯遇到的问题,主要是for循环+递归这段有点绕,在N后问题、和本次作业第二题都用了这种方式求解,要捋清楚思路有点困难。