方法一:递归code
从1~n中,取数,使其和为sum。递归
list<int> list1; void SumOfkNum( int sum, int n){ if( n<=0 || sum<=0) return; if( sum==n){ list1.reverse(); //output from min_value for( list<int>::iterator iter = list1.begin(); iter!=list1.end(); iter++) cout<<*iter<<"+"; cout<<n<<endl; list1.reverse(); //recover } list1.push_front( n); SumOfkNum( sum-n, n-1); list1.pop_front( n); SumOfkNum( sum, n-1); }
方法二:回溯it
t = Σ(1,...,k-1)WiXi, r = Σ(k,...,n)Wiclass
W={ 1, 2, ..., n}, 因此 Wk=k。t为已求和,Wi表示第i件物品的价值, Xi表示添加第 i件物品的添加数量。咱们这里由于每一个数只能取一次,因此 Xi 都为 true或 false。方法
void SumOfkNum( int t, int k, int r, int &m, bool &flag, bool *x){ x[k]=true; //输入t和r,尝试Wk if( t+k==M){ //若找到一个和为m,则设置解向量的标志位,输出解 flag = true; for( int i=1; i<=k; ++i) if( x[i] == true) printf("%d ",i); printf("\n"); }else{ //若第k+1个数知足条件,则递归左子树 if( t+k+(k+1) <=m ) SumOfkNum( t+k, k+1, r-k, m, flag, x); //若不选第k个数,选第k+1个数知足条件,则递归右子树 if( (t+r-k >=m) && (t+(k+1)<=m)){ x[k] = false; SumOfkNum( t, k+1, r-k, m, flag, x); } } } void search( int &n, int &m){ //初始化解空间 bool *x=(bool*)malloc(sizeof(bool)*(n+1)); memset( x, false, sizeof(bool)*(n+1)); int sum = (n+1)*n/2; if( 1>m || sum<m){ //预先排除无解状况 printf("not found\n"); return; } bool f = false; SumOfkNum( 0, 1, sum, m, f, x); if( !f) printf("not found\n"); free( x); }