和等于 m的任意可能组合

编程求解:
输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,
使其和等于 m ,要求将其中所有的可能组合列出来.

//coder:LEE
//20120315
#include<iostream>
#include<cassert>
#include<vector>
using namespace std;
//solution1
void Combine(int beg,int end,int GetN,vector<int> &v,int m)
{
if (GetN==0)
{
int sum=0;
for (vector<int>::iterator p=v.begin();p!=v.end();++p)
{
sum+=*p;
}
if(sum==m)
{
for (vector<int>::iterator p=v.begin();p!=v.end();++p)
{
cout<<*p<<" ";
}
cout<<endl;
}
return;
}
for (int i=beg;i<=end;i++)
{
v.push_back(i);
--GetN;
Combine(i+1,end,GetN,v,m);
++GetN;
v.pop_back();
}
}
void FindDigitsEquelToM(int n,int m)//递归解法
{
assert(n>0&&m>0);
vector<int> v;
for (int i=1;i<=n;i++)
{
Combine(1,n,i,v,m);
}
}
//solution2
void FindDigitsEquelToMNoRecurion(int n,int m)//类似0-1背包问题,非递归解法
{
vector<int> index;
int front=1;
int sum=0;
while (front<=n)
{
if (sum+front<m)//小于m,加入容器
{
index.push_back(front);
sum+=front;
}
else if (sum+front==m)//等于m,输出容器中的数字,pop容器,更新front
{
for (vector<int>::iterator beg=index.begin();beg!=index.end();++beg)
cout<<*beg<<" ";
cout<<front<<endl;
if(index.empty())
break;
front=index.back();
index.pop_back();
sum-=front;
}
else//大于m,pop容器,更新front
{
if(index.empty())
break;
front=index.back();
index.pop_back();
sum-=front;
}
front++;
while(front>n&&!index.empty())//如果front越界,容器非空,则pop容器,更新front,直到小于n
{
front=index.back();
index.pop_back();
sum-=front;
front++;

}
}


}
//solution3
int sum=0;
void BackTrack(int n,int m,vector<int> &v,int i)
{
if(i>n)
return;
if (i+sum<m)
{
sum+=i;
v.push_back(i);
BackTrack(n,m,v,i+1);
sum-=i;
v.pop_back();
BackTrack(n,m,v,i+1);
}
else
{
if (i+sum==m)
{
for (vector<int>::iterator beg=v.begin();beg!=v.end();++beg)
cout<<*beg<<" ";
cout<<i<<endl;
}
return;
}
}
int main()
{
const int n=15;
const int m=11;
FindDigitsEquelToM(n,m);
cout<<endl;
// FindDigitsEquelToMNoRecurion(n,m);
vector<int> v;
BackTrack(n,m,v,1);
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值