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