这是一道很明显的动态规划的题目。
递推公式为
用sum(n, m)表示所有可能的1~n之间存在的和为m的组合
那么 sum(n,m) = sum(n-1, m) | sum(n-1, m-n)
直接上代码
void FindCombine(std::list la, int n,int m){ if(m < 0 ) return ; if(m == 0) { for(std::list ::iterator iter = la.begin();iter!=la.end();iter ++) { std::cout<<*iter<<"+"; } cout << endl; return ; } if(n <= 0) { return ; } la.push_back(n); FindCombine(la,n-1,m-n); la.pop_back(); FindCombine(la,n-1,m);}
如果允许选择重复的数字呢?
递推公式为
sum(n,m) = sum(n-1, m) | sum(n, m-n)
只需要将上面的代码稍作修改
void FindCombine(std::list &la, int n,int m){ if(n <= 0 || m <= 0) { return ; } if(n == m) { for(std::list ::iterator iter = la.begin();iter!=la.end();iter ++) { std::cout<<*iter<<"+"; } std::cout<<
还有另外一种解法
void FindCombine1(std::list &la, int n,int m){ if(m < 0) { return ; } if(m == 0) { for(std::list ::iterator iter = la.begin();iter!=la.end();iter ++) { std::cout<<*iter<<"+"; } cout << endl; return ; } if(n <= 0) { return ; } for(int i = n; i>0 ;i--) { la.push_back(i); FindCombine1(la,i,m-i); la.pop_back(); }}