一,题目:输入两个整数 n 和 m,从数列1,2,3.......n 中随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来。
二,解释:比如输入m=4 n=4 则输出为:4
1+3 而2+2不正确,因为重复输出数字了
中心思想:1)如果1+2+3+……+n<m 则不存在这个数
2)如果m<n 则应该让n=m //因为m--->n之间的数都已经大于m了 没必要再计算了
3)如果m=n 输出n
4)如果m>n 递归循环
源码采用原型:0-1背包问题
参考博客:http://blog.csdn.net/tianshuai11/article/details/7025464
三,源码:(类似源码五)
#include<list>
#include<iostream>
using namespace std;
list<int> list1;
void find_factor(int sum, int n)
{
// 递归出口
if(n <= 0 || sum <= 0)
return;
// 输出找到的结果
if(sum == n)
{
// 反转list
list1.reverse();
for(list<int>::iterator iter = list1.begin(); iter != list1.end(); iter++)
cout << *iter << " + ";
cout << n << endl;
list1.reverse();
}
list1.push_front(n); //典型的01背包问题
find_factor(sum-n, n-1); //放n,n-1个数填满sum-n
list1.pop_front();
find_factor(sum, n-1); //不放n,n-1个数填满sum
}
int main()
{
int sum, n;
cout << "请输入你要等于多少的数值sum:" << endl;
cin >> sum;
cout << "请输入你要从1.....n数列中取值的n:" << endl;
cin >> n;
cout << "所有可能的序列,如下:" << endl;
find_factor(sum,n);
return 0;
}
四,源码(java方法)
/**
* 输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,
使其和等于 m ,要求将其中所有的可能组合列出来.
e.g
n=6,m=6 1,2,3 2,4 1,5
n=
* @author wangxm
*/
public class Comp {
static void getAllComp(int n,int m){
String pre = m+"=";
int theMax = (1+n)*n/2;
if(theMax<m){
System.out.println("不存在该数!");
}else{
for(int i=1;i<=m/2;i++){
//从1开始计数,打印出两个数的组合,并且两数不相等
if(i != m-i)
System.out.println(pre+i+"+"+(m-i));
//调用递归,继续求得大于2个数的组合
getTheResult(m-i,pre+i,i);
}
}
}
//调用递归,继续求得大于2个数的组合,j为组合中已用过的数,所以取大于该数的。
static void getTheResult(int m,String pre,int j){
for(int i=j+1;i<=m/2;i++){
if(i != m-i)
System.out.println(pre+"+"+i+"+"+(m-i));
getTheResult(m-i,pre+"+"+i,i);
}
}
public static void main(String[] args) {
getAllComp(3,6);
}
}
五,源码(容易理解)
#include <iostream>
using namespace std;
int length;
void PrintSolution(int *flag)
{
for (int i=0;i<length;i++)
{
if (flag[i]==1)
{
cout<<i+1<<" ";
}
}
cout<<endl;
}
void BagProblem(int m,int n, int *flag)
{
if (n<1||m<1)
return;
if (m<n)
n=m;
if (n==m)
{
flag[n-1]=1;
PrintSolution(flag);
flag[n-1]=0;
}
flag[n-1]=1; //n先放入背包中
BagProblem(m-n,n-1,flag); //剩余空间为 m-n 可以取的背包为 1->n-1
flag[n-1]=0; //n不放入背包中
BagProblem(m,n-1,flag); //剩余空间为 m 可以取的背包为 1->n-1
}
int main() {
int m,n;
cout<<"please input m and n:"<<endl;
cin>>m>>n;
cout<<"the solution is :"<<endl;
length=n;
int *flag=(int *)malloc(sizeof(int)*n);
memset(flag,0,sizeof(int)*n);//注意memset用法及区分sizeof(flag)/sizeof(int)*n
BagProblem(m,n,flag);
free(flag);
return 0;
}
【0-1背包公式】opt[i][v] = max(opt[i-1][v] , opt[i-1][v-c[i]] + w[i])
解释如下:
opt[i-1][v] 表示第i件物品不装入背包中,而opt[i-1][v-c[i]] + w[i] 表示第i件物品装入背包中。
对应之后:n为物品 m为背包容积,这里相当于求“所有可能的装满的装法”。忽略了价值的计算即没有真正计算出那种装法最佳