Java求解,输入两个整数n和m,从数列1,2,3,……n中随意取几个数,使其和等于m。要求将所有的可能组合列出来(背包动态规划问题求解)
输入两个整数n和m,从数列1,2,3,……n中随意取几个数,使其和等于m。要求将所有的可能组合列出来。
之前看到有同学写该问题的Java版本,但是照着运行了一下,发现还是存在问题,经过自己的查资料研究,特写出Java版本的正确解答;
该问题初始大概的想法就是:
1)第一种情况,含有n,则递归调用函数求 从1,2,3 到n-1取任意几个数,组成m-n;
2)第二种情况,不含n,则递归调用函数求从1,2,3 到n取任意几个数,组成m;
有了问题的大概想法后,则需要判断特殊条件:
1)如果n大于m,则大于m的数都不能抽取,该问题化为从1,2,3 到m抽取任意几个数组成m;
2)边界值问题,何时为递归的结束条件,分一下三种情况:第一种:m==0&&n>=0,此时应该结束,打印结果,返回;第二种情况:n>=1&&m==1,则直接从n中取1,,压入linkedlist中,打印结果,再pop出1,返回; 第三种情况:n==1&&m>1,则直接返回,该中组合不能构成m;
import java.util.LinkedList;
/**
* @author yuchen
* @version 1.0
* @date 2020-05-20 15:21
*/
public class N {
private static LinkedList<Integer> list=new LinkedList<Integer>();
public static void main(String[] args) {
int n = 6;
int m = 10;
findSum(m,n);
}
public static void findSum(int sum,int n){
//数组有序 m=0 n的范围是1-n所以 这种情况 直接不存在 打印空集合
if(sum == 0 && n >= 0){
myPrint();
return;
}
//和是1 n>=1 因为1-n 所以把1放到集合里 打印出来后 再移除
if(sum == 1 && n >= 1){
list.push(1);
myPrint();
list.pop();
return;
}
//最小元素就是1 sum的和>1 所以没有
if(sum > 1 && n == 1 ){
return;
}
if(sum >= n){
//sum包含n的情况 剩下的集合中 计算出sum = sum-n的情况
list.push(n);
findSum(sum - n ,n-1);
list.pop();
//sum不包含n的情况 即sum > n
findSum(sum ,n-1);
}else{
//sum < n的情况
findSum(sum ,sum);
}
return;
}
public static void myPrint(){
for(int i=0;i<list.size();i++){
System.out.print(list.get(i));
}
System.out.println();
}
}